<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Response;
use App\Models\InvoiceModel;
use App\Helpers\InvoiceHelper;
use App\Helpers\PDFHelper;
use App\Helpers\InvoiceEmailHelper;
use Exception;

class InvoiceController extends Controller
{
    private InvoiceModel $invoiceModel;

    public function __construct()
    {
        $this->invoiceModel = new InvoiceModel();
    }

    public function index(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $filters = $_GET;
        $page = (int) ($_GET['page'] ?? 1);
        $perPage = (int) ($_GET['per_page'] ?? 20);

        $results = $this->invoiceModel->getAll($tenantId, $filters, $page, $perPage);
        $results['stats'] = $this->invoiceModel->getStats($tenantId, $filters);
        
        Response::success($results);
    }

    public function show(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $invoice = $this->invoiceModel->getById((int)$id, $tenantId);

        if (!$invoice) {
            Response::error('Invoice not found', [], 404);
            return;
        }

        $tenantModel = new \App\Models\TenantModel();
        $invoice['tenant'] = array_merge($tenantModel->find($tenantId) ?? [], $tenantModel->getSettings($tenantId) ?? []);

        Response::success($invoice);
    }

    public function store(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        $this->validate($data, [
            'customer_id' => 'required',
            'items' => 'required|array'
        ]);

        try {
            $result = $this->invoiceModel->createInvoice($tenantId, $data, $userId);
            Response::success($result, 'Invoice created successfully', 201);
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function update(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        $this->validate($data, [
            'customer_id' => 'required',
            'items' => 'required|array'
        ]);

        try {
            $result = $this->invoiceModel->updateInvoice((int)$id, $tenantId, $data, $userId);
            Response::success($result, 'Invoice updated successfully');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function destroy(string $id): void
    {
        // Actually same as cancel logic for drafts
        $this->cancel($id);
    }

    public function cancel(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        try {
            $this->invoiceModel->cancel((int)$id, $tenantId, $userId);
            Response::success([], 'Invoice cancelled correctly');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function duplicate(string $id): void
    {
        // Clone an invoice
        Response::error("Clone feature coming soon.");
    }

    public function nextNumber(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        try {
            $nextNum = InvoiceHelper::generateInvoiceNumber($tenantId);
            Response::success(['invoice_number' => $nextNum]);
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function calculate(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $data = $this->getJsonBody();
        try {
            $discountType = $data['discount_type'] ?? 'percent';
            $discountValue = (float)($data['discount_value'] ?? 0);
            $isInterstate = isset($data['is_interstate']) ? (bool)$data['is_interstate'] : false;
            
            $calculated = \App\Helpers\GSTHelper::calculateInvoiceTotals($data['items'] ?? [], $discountType, $discountValue, $isInterstate);
            Response::success($calculated);
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function recordPayment(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        $this->validate($data, [
            'amount' => 'required|numeric'
        ]);

        try {
            $result = $this->invoiceModel->recordPayment((int)$id, $data, $tenantId, $userId);
            Response::success($result, 'Payment recorded successfully');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function getPayments(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $payments = $this->invoiceModel->getPayments((int)$id, $tenantId);
        Response::success($payments);
    }

    public function pdf(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        try {
            $invoice = $this->invoiceModel->getById((int)$id, $tenantId);
            if (!$invoice) throw new Exception("Invoice not found.");

            $tenantModel = new \App\Models\TenantModel();
            $tenantProfile = $tenantModel->find($tenantId) ?? [];
            $tenantSettings = $tenantModel->getSettings($tenantId) ?? [];
            
            // Merge profile and settings for PDF
            $businessDetails = array_merge($tenantProfile, $tenantSettings);
            $businessDetails['email'] = $tenantProfile['email'] ?? $businessDetails['email'] ?? '';
            
            PDFHelper::stream($invoice, $businessDetails, $invoice['template'] ?? 'classic');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function send(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        try {
            $invoice = $this->invoiceModel->getById((int)$id, $tenantId);
            if (!$invoice) throw new Exception("Invoice not found.");

            $tenantSettings = [
                'business_name' => 'Acme Corp',
                'address' => '123 Business St',
                'gstin' => '27AAACA1234A1Z5',
                'email' => 'billing@acme.com',
                'phone' => '+91-9876543210'
            ];

            $pdfPath = PDFHelper::generate($invoice, $tenantSettings, $invoice['template'] ?? 'classic');
            
            $customer = [
                'name' => $invoice['customer_name'],
                'email' => $invoice['customer_email']
            ];

            InvoiceEmailHelper::sendInvoice($invoice, $customer, $tenantSettings, $pdfPath);

            Response::success([], 'Invoice sent to customer.');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function reminder(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        try {
            $invoice = $this->invoiceModel->getById((int)$id, $tenantId);
            if (!$invoice) throw new Exception("Invoice not found.");

            $tenantSettings = [
                'business_name' => 'Acme Corp',
                'email' => 'billing@acme.com'
            ];
            
            $customer = [
                'name' => $invoice['customer_name'],
                'email' => $invoice['customer_email']
            ];

            InvoiceEmailHelper::sendPaymentReminder($invoice, $customer, $tenantSettings);

            Response::success([], 'Reminder sent.');
        } catch (Exception $e) {
            Response::error($e->getMessage());
        }
    }

    public function viewPublic(string $id): void
    {
        // Public viewing endpoint, mark as viewed logic
        Response::error("Public view returning PDF template viewer not implemented natively here yet.", [], 501);
    }
}
