<?php

namespace App\Modules\CRM\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Responses\ApiResponse;
use App\Modules\CRM\Models\Lead;
use App\Modules\CRM\Requests\StoreActivityRequest;
use App\Modules\CRM\Requests\StoreLeadRequest;
use App\Modules\CRM\Requests\UpdateLeadRequest;
use App\Modules\CRM\Resources\ActivityResource;
use App\Modules\CRM\Resources\LeadResource;
use App\Modules\Invoice\Models\Customer;
use App\Modules\Invoice\Resources\CustomerResource;
use App\Modules\Tenant\Models\Company;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class LeadController extends Controller
{
    public function summary(Request $request): JsonResponse
    {
        $company = $this->currentCompany($request);

        $leads = Lead::query()
            ->where('company_id', $company->id)
            ->get();

        return ApiResponse::success([
            'total_leads' => $leads->count(),
            'open_leads' => $leads->where('status', 'open')->count(),
            'won_leads' => $leads->where('stage', 'won')->count(),
            'pipeline_value' => number_format((float) $leads->where('status', 'open')->sum('deal_value'), 2, '.', ''),
        ]);
    }

    public function index(Request $request): JsonResponse
    {
        $company = $this->currentCompany($request);
        $query = $this->filteredLeadsQuery($company);

        if ($request->hasAny(['page', 'per_page'])) {
            $perPage = min(max((int) $request->query('per_page', 15), 1), 100);
            $paginator = $query->paginate($perPage);

            return ApiResponse::success([
                'data' => LeadResource::collection($paginator->items()),
                'meta' => [
                    'current_page' => $paginator->currentPage(),
                    'from' => $paginator->firstItem(),
                    'last_page' => $paginator->lastPage(),
                    'per_page' => $paginator->perPage(),
                    'to' => $paginator->lastItem(),
                    'total' => $paginator->total(),
                ],
            ]);
        }

        return ApiResponse::success(LeadResource::collection($query->get()));
    }

    public function store(StoreLeadRequest $request): JsonResponse
    {
        $company = $this->currentCompany($request);
        $data = $request->validated();

        $lead = Lead::query()->create([
            ...$data,
            'company_id' => $company->id,
            'stage' => $data['stage'] ?? 'new',
            'deal_value' => $data['deal_value'] ?? 0,
            'status' => in_array($data['stage'] ?? 'new', ['won', 'lost'], true) ? 'closed' : 'open',
        ]);

        return ApiResponse::success(
            new LeadResource($lead->load('activities')),
            'Lead created successfully',
            201
        );
    }

    public function update(UpdateLeadRequest $request, Lead $lead): JsonResponse
    {
        $company = $this->currentCompany($request);

        if ((int) $lead->company_id !== (int) $company->id) {
            return ApiResponse::error('Lead not found', 404);
        }

        $data = $request->validated();

        if (isset($data['stage']) && in_array($data['stage'], ['won', 'lost'], true) && ! isset($data['status'])) {
            $data['status'] = 'closed';
        }

        $lead->update($data);

        return ApiResponse::success(
            new LeadResource($lead->load('activities')),
            'Lead updated successfully'
        );
    }

    public function storeActivity(StoreActivityRequest $request, Lead $lead): JsonResponse
    {
        $company = $this->currentCompany($request);

        if ((int) $lead->company_id !== (int) $company->id) {
            return ApiResponse::error('Lead not found', 404);
        }

        $data = $request->validated();

        $activity = $lead->activities()->create([
            'company_id' => $company->id,
            'user_id' => $request->user()?->id,
            'type' => $data['type'] ?? 'note',
            'subject' => $data['subject'],
            'description' => $data['description'] ?? null,
            'activity_date' => $data['activity_date'] ?? now()->toDateString(),
            'next_follow_up_at' => $data['next_follow_up_at'] ?? null,
        ]);

        if (! empty($data['next_follow_up_at'])) {
            $lead->update(['next_follow_up_at' => $data['next_follow_up_at']]);
        }

        return ApiResponse::success(
            new ActivityResource($activity),
            'Activity added successfully',
            201
        );
    }

    public function convertToCustomer(Request $request, Lead $lead): JsonResponse
    {
        $company = $this->currentCompany($request);

        if ((int) $lead->company_id !== (int) $company->id) {
            return ApiResponse::error('Lead not found', 404);
        }

        $customer = DB::transaction(function () use ($company, $lead): Customer {
            if ($lead->customer_id) {
                return Customer::query()
                    ->where('company_id', $company->id)
                    ->findOrFail($lead->customer_id);
            }

            $customer = Customer::query()->create([
                'company_id' => $company->id,
                'name' => $lead->name,
                'email' => $lead->email,
                'phone' => $lead->phone,
                'address' => $lead->company_name,
                'status' => 'active',
            ]);

            $lead->update([
                'customer_id' => $customer->id,
                'stage' => 'won',
                'status' => 'closed',
            ]);

            return $customer;
        });

        return ApiResponse::success(
            new CustomerResource($customer),
            'Lead converted to customer successfully'
        );
    }

    private function currentCompany(Request $request): Company
    {
        return $request->attributes->get('currentCompany');
    }

    /**
     * @return Builder<Lead>
     */
    private function filteredLeadsQuery(Company $company): Builder
    {
        return Lead::query()
            ->where('company_id', $company->id)
            ->with('activities')
            ->latest();
    }
}
