<?php

declare(strict_types=1);

namespace App\Http\Controllers\Project;

use App\Http\Controllers\Concerns\AuthorizesProjectAccess;
use App\Http\Controllers\Controller;
use App\Http\Resources\ProjectSummaryResource;
use App\Models\Invoice;
use App\Models\MediaItem;
use App\Models\Project;
use App\Models\ProjectCompletion;
use App\Models\Report;
use App\Notifications\SimpleDatabaseNotification;
use App\Support\ApiResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class ProjectCompletionController extends Controller
{
    use AuthorizesProjectAccess;

    public function completable(Request $request)
    {
        if (! $request->user()->hasRole('admin')) {
            return ApiResponse::forbidden('فقط ادمین به این لیست دسترسی دارد.');
        }

        $query = Project::query()
            ->withApiRelations()
            ->with('completion')
            ->whereNotIn('status', [Project::STATUS_COMPLETED, Project::STATUS_CANCELLED])
            ->where(function ($builder): void {
                $builder->whereDate('end_date', '<=', now())
                    ->orWhereHas('invoices', fn ($q) => $q->where('status', Invoice::STATUS_PAID));
            });

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }

        if ($request->filled('category_id')) {
            $query->where('category_id', $request->integer('category_id'));
        }

        if ($request->filled('from')) {
            $query->whereDate('end_date', '>=', $request->date('from'));
        }

        if ($request->filled('to')) {
            $query->whereDate('end_date', '<=', $request->date('to'));
        }

        $perPage = min($request->integer('per_page', 15), 50);

        return ProjectSummaryResource::collection($query->paginate($perPage));
    }

    public function show(Project $project)
    {
        $this->authorizeProjectAccess($project);

        $project->loadApiRelations()->load(['completion']);

        $paidInvoices = $project->invoices()->where('status', Invoice::STATUS_PAID)->count();
        $reportsCount = $project->reports()->count();
        $approvedReports = $project->reports()->where('workflow_status', Report::WORKFLOW_APPROVED)->count();
        $mediaCount = $project->mediaItems()->where('status', MediaItem::STATUS_APPROVED)->count();

        $completion = $project->completion;

        return ApiResponse::success([
            'project' => new ProjectSummaryResource($project),
            'checklist' => [
                'end_date_passed' => $project->end_date && $project->end_date->isPast(),
                'paid_invoices_count' => $paidInvoices,
                'reports_count' => $reportsCount,
                'approved_reports_count' => $approvedReports,
                'media_count' => $mediaCount,
                'in_arbitration' => $project->status === Project::STATUS_ARBITRATION,
            ],
            'completion' => $completion ? [
                'id' => $completion->id,
                'started_at' => $completion->started_at?->toISOString(),
                'producer_confirmed_at' => $completion->producer_confirmed_at?->toISOString(),
                'employer_confirmed_at' => $completion->employer_confirmed_at?->toISOString(),
                'finalized_at' => $completion->finalized_at?->toISOString(),
                'notes' => $completion->notes,
            ] : null,
        ]);
    }

    public function start(Request $request, Project $project)
    {
        if (! $request->user()->hasRole('admin')) {
            return ApiResponse::forbidden('فقط ادمین می‌تواند فرآیند پایان پروژه را آغاز کند.');
        }

        Gate::authorize('update', $project);

        if ($project->status === Project::STATUS_COMPLETED) {
            return ApiResponse::badRequest('پروژه قبلاً تکمیل شده است.');
        }

        $completion = ProjectCompletion::updateOrCreate(
            ['project_id' => $project->id],
            [
                'started_by' => $request->user()->id,
                'started_at' => now(),
                'notes' => $request->input('notes'),
                'finalized_at' => null,
                'finalized_by' => null,
            ]
        );

        $project->update([
            'status' => Project::STATUS_WAITING,
            'updated_by' => $request->user()->id,
        ]);

        $project->loadMissing('producer.user');
        if ($project->producer?->user) {
            $project->producer->user->notify(new SimpleDatabaseNotification(
                'درخواست ثبت پایان پروژه',
                "ادمین فرآیند پایان پروژه «{$project->name}» را آغاز کرده است. لطفاً پایان پروژه را در سیستم تأیید کنید.",
                ['type' => 'project_completion_start', 'project_id' => $project->id]
            ));
        }

        return ApiResponse::success([
            'completion' => $completion,
            'project' => new ProjectSummaryResource($project->fresh()->loadApiRelations()),
        ], 'فرآیند پایان پروژه آغاز شد.');
    }

    public function confirm(Request $request, Project $project)
    {
        $this->authorizeProjectAccess($project);

        $completion = $project->completion;
        if (! $completion || ! $completion->started_at) {
            return ApiResponse::badRequest('فرآیند پایان پروژه هنوز آغاز نشده است.');
        }

        if ($completion->isFinalized()) {
            return ApiResponse::badRequest('پروژه قبلاً نهایی شده است.');
        }

        $user = $request->user();
        $project->loadMissing('producer');

        $isProducer = $project->producer && $project->producer->user_id === $user->id;
        $isEmployer = $user->id === $project->user_id;

        if (! $isProducer && ! $isEmployer && ! $user->hasRole('admin')) {
            return ApiResponse::forbidden('شما مجاز به تأیید پایان این پروژه نیستید.');
        }

        if ($isProducer || ($user->hasRole('admin') && $request->input('as') === 'producer')) {
            $completion->update(['producer_confirmed_at' => now()]);
            if ($project->user) {
                $project->user->notify(new SimpleDatabaseNotification(
                    'تأیید پایان پروژه توسط تولیدکننده',
                    "تولیدکننده پایان پروژه «{$project->name}» را تأیید کرد. لطفاً در بازه زمانی مشخص تأیید نهایی را انجام دهید.",
                    ['type' => 'project_completion_producer', 'project_id' => $project->id]
                ));
            }
        }

        if ($isEmployer || ($user->hasRole('admin') && $request->input('as') === 'employer')) {
            $completion->update(['employer_confirmed_at' => now()]);
        }

        return ApiResponse::success([
            'completion' => $completion->fresh(),
            'project' => new ProjectSummaryResource($project->fresh()->loadApiRelations()),
        ], 'تأیید پایان پروژه ثبت شد.');
    }

    public function finalize(Request $request, Project $project)
    {
        if (! $request->user()->hasRole('admin')) {
            return ApiResponse::forbidden('فقط ادمین می‌تواند پایان پروژه را نهایی کند.');
        }

        Gate::authorize('update', $project);

        $completion = $project->completion;
        if (! $completion || ! $completion->started_at) {
            return ApiResponse::badRequest('فرآیند پایان پروژه هنوز آغاز نشده است.');
        }

        if ($project->status === Project::STATUS_ARBITRATION) {
            return ApiResponse::badRequest('پروژه در وضعیت داوری است و تا رسیدگی قابل نهایی‌سازی نیست.');
        }

        $completion->update([
            'finalized_at' => now(),
            'finalized_by' => $request->user()->id,
            'notes' => $request->input('notes', $completion->notes),
        ]);

        $project->update([
            'status' => Project::STATUS_COMPLETED,
            'updated_by' => $request->user()->id,
        ]);

        foreach (array_filter([$project->user, $project->producer?->user]) as $notifyUser) {
            $notifyUser->notify(new SimpleDatabaseNotification(
                'پایان پروژه',
                "پروژه «{$project->name}» به‌صورت رسمی پایان یافت.",
                ['type' => 'project_completion_finalized', 'project_id' => $project->id]
            ));
        }

        return ApiResponse::success([
            'completion' => $completion->fresh(),
            'project' => new ProjectSummaryResource($project->fresh()->loadApiRelations()),
        ], 'پایان پروژه نهایی شد.');
    }
}
