<?php

namespace App\Http\Controllers;

use App\Mail\ContractClientMail;
use Illuminate\Support\Facades\Mail;
use App\Models\Contract;
use App\Models\ContractPayment;
use App\Models\Job;
use App\Models\Contact;
use App\Models\ActivityLog;
use Carbon\Carbon;
use Illuminate\Http\Request;

class ContractController extends Controller
{
    public function index(Request $request)
    {
        $query = Contract::with(['job', 'contact']);
        if ($request->status && $request->status !== 'all') {
            $query->where('status', $request->status);
        }
        $contracts = $query->latest()->paginate(20)->withQueryString();

        $stats = [
            'all'         => Contract::count(),
            'draft'       => Contract::where('status', 'draft')->count(),
            'signed'      => Contract::where('status', 'signed')->count(),
            'in_progress' => Contract::where('status', 'in_progress')->count(),
            'completed'   => Contract::where('status', 'completed')->count(),
        ];

        return view('contracts.index', compact('contracts', 'stats'));
    }

    public function create()
    {
        $jobs = Job::with('contact')->latest()->get();
        $contacts = Contact::orderBy('first_name')->get();
        return view('contracts.create', compact('jobs', 'contacts'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'job_id'          => 'nullable|exists:crm_jobs,id',
            'contact_id'      => 'nullable|exists:contacts,id',
            'contract_price'  => 'required|numeric|min:0',
            'deposit_pct'     => 'nullable|numeric|min:0|max:100',
            'cm_pct'          => 'nullable|numeric|min:0|max:100',
            'delivery_pct'    => 'nullable|numeric|min:0|max:100',
            'completion_pct'  => 'nullable|numeric|min:0|max:100',
            'inclusions'      => 'nullable|string',
            'exclusions'      => 'nullable|string',
            'terms'           => 'nullable|string',
            'notes'           => 'nullable|string',
        ]);

        $data['contract_number'] = 'C-' . str_pad((Contract::withTrashed()->max('id') ?? 0) + 1, 4, '0', STR_PAD_LEFT);
        $data['status'] = 'draft';
        $data['deposit_pct'] = $data['deposit_pct'] ?? 30;
        $data['cm_pct'] = $data['cm_pct'] ?? 20;
        $data['delivery_pct'] = $data['delivery_pct'] ?? 20;
        $data['completion_pct'] = $data['completion_pct'] ?? 30;

        $contract = Contract::create($data);

        return redirect()->route('contracts.show', $contract)->with('success', "Contract {$contract->contract_number} created.");
    }

    public function show(Contract $contract)
    {
        $contract->load(['job', 'contact', 'documents.uploader']);
        return view('contracts.show', compact('contract'));
    }

    public function edit(Contract $contract)
    {
        $jobs = Job::with('contact')->latest()->get();
        $contacts = Contact::orderBy('first_name')->get();
        return view('contracts.edit', compact('contract', 'jobs', 'contacts'));
    }

    public function update(Request $request, Contract $contract)
    {
        $data = $request->validate([
            'contract_price' => 'nullable|numeric|min:0',
            'deposit_pct'    => 'nullable|numeric|min:0|max:100',
            'cm_pct'         => 'nullable|numeric|min:0|max:100',
            'delivery_pct'   => 'nullable|numeric|min:0|max:100',
            'completion_pct' => 'nullable|numeric|min:0|max:100',
            'inclusions'     => 'nullable|string',
            'exclusions'     => 'nullable|string',
            'terms'          => 'nullable|string',
            'notes'          => 'nullable|string',
        ]);
        $contract->update($data);
        return redirect()->route('contracts.show', $contract)->with('success', 'Contract updated.');
    }

    public function send(Contract $contract)
    {
        $contract->load(['contact', 'job.lead.contact']);
       

        // Prefer the lead's contact email (the lead attached to the job)
        $leadContact = $contract->job?->lead?->contact;
        $emailContact = ($leadContact && $leadContact->email) ? $leadContact : $contract->contact;

        $email = $emailContact?->email;
        //dd($email);
        $email = "debayan.sen@shyamfuture.com";
        //dd($email);
        if (!$email) {
            return back()->with('error', 'No email address found for the lead on this job. Please add one to the lead contact.');
        }

        // Apply dynamic SMTP config from settings
        //$this->applySmtpFromSettings();

        try {
            $clientName = $emailContact->full_name ?? $emailContact->first_name;
            //dd($clientName);
            Mail::to($email, $clientName)->send(new ContractClientMail($contract));

            $contract->update(['status' => 'sent']);

             ActivityLog::create([
                'user_id' => auth()->id(), 'loggable_type' => 'Contract', 'loggable_id' => $contract->id,
                'action' => 'Contract Sent', 'description' => "Contract {$contract->contract_number} sent to client",
            ]);

            return back()->with('success', "Contract emailed to {$email} successfully.");
        } catch (\Exception $e) {
            logger($e->getMessage());
            return back()->with('error', 'Failed to send email: ' . $e->getMessage());
        }
    }

    public function markSigned(Request $request, Contract $contract)
    {
        $contract->update([
            'status'      => 'signed',
            'signed_date' => $request->signed_date ?? Carbon::today(),
        ]);

        // Advance job to contracts stage if it hasn't moved yet
        if ($contract->job) {
            $contract->job->update(['stage' => 'contracts','contract_signed'=>true]);
        }

        ActivityLog::create([
            'user_id' => auth()->id(), 'loggable_type' => 'Contract', 'loggable_id' => $contract->id,
            'action' => 'Contract Signed', 'description' => "Contract {$contract->contract_number} marked as signed",
        ]);

        return back()->with('success', 'Contract marked as signed.');
    }

    public function markPayment(Request $request, Contract $contract, string $field)
    {
        $typeMap = [
            'deposit_paid'    => 'deposit',
            'cm_paid'         => 'check_measure',
            'delivery_paid'   => 'delivery',
            'completion_paid' => 'completion',
        ];

        if (! array_key_exists($field, $typeMap)) {
            abort(422, 'Invalid payment field.');
        }

        $amountMap = [
            'deposit_paid'    => $contract->depositAmount(),
            'cm_paid'         => $contract->cmAmount(),
            'delivery_paid'   => $contract->deliveryAmount(),
            'completion_paid' => $contract->completionAmount(),
        ];

        // Set the boolean flag
        $contract->update([$field => true]);

        if($field == 'deposit_paid'){
            $contract->job->update(['deposit_paid' => true,'deposit_amount'=>$contract->depositAmount()]);
        }
        if($field == 'cm_paid'){
            $contract->job->update(['cm_paid' => true]);
        }
        if($field == 'delivery_paid'){
            $contract->job->update(['delivery_paid' => true]);
        }
        if($field == 'completion_paid'){
            $contract->job->update(['final_paid' => true]);
        }

        // Record a ContractPayment ledger entry (idempotent via firstOrCreate)
        ContractPayment::firstOrCreate(
            ['contract_id' => $contract->id, 'payment_type' => $typeMap[$field]],
            [
                'job_id'      => $contract->job_id,
                'amount'      => $amountMap[$field],
                'paid_date'   => $request->paid_date ? Carbon::parse($request->paid_date) : Carbon::today(),
                'is_paid'     => true,
                'method'      => $request->method ?? 'bank_transfer',
                'reference'   => $request->reference,
                'notes'       => $request->notes,
                'recorded_by' => auth()->id(),
            ]
        );

        // Auto-advance contract status based on payment progress
        $fresh = $contract->fresh();
        $newStatus = match(true) {
            $fresh->completion_paid => 'completed',
            $fresh->delivery_paid   => 'in_progress',
            $fresh->deposit_paid    => 'deposit_paid',
            default                 => $fresh->status,
        };
        if ($newStatus !== $fresh->status) {
            $contract->update(['status' => $newStatus]);
        }

        ActivityLog::create([
            'user_id'       => auth()->id(),
            'loggable_type' => 'Contract',
            'loggable_id'   => $contract->id,
            'action'        => 'Payment Recorded',
            'description'   => "Contract {$contract->contract_number}: " . ucwords(str_replace('_', ' ', $typeMap[$field])) . " payment of \$" . number_format($amountMap[$field]),
        ]);

        return back()->with('success', ucwords(str_replace('_', ' ', $field)) . ' recorded in ledger.');
    }

    public function destroy(Contract $contract)
    {
        $contract->delete();
        return redirect()->route('contracts.index')->with('success', 'Contract deleted.');
    }
}
