<?php
namespace App\Controllers;

use App\Core\Controller;
use App\Models\Client;
use App\Models\Deposit;
use App\Models\ClientTransaction;
use App\Services\EmailService;
use App\Services\SmsService;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use Dompdf\Dompdf;
use Dompdf\Options;

class ClientController extends Controller
{
    /**
     * List all clients
     */
    public function index()
    {
        $this->requireAuth();
        $clientModel = new Client();
        $clients = $clientModel->getAll();
        $this->render('clients/index', ['clients' => $clients]);
    }

    /**
     * Show form to create a new client
     */
    public function create()
    {
        $this->requireAuth();
        $this->render('clients/create');
    }

    /**
     * Store a new client
     */
    public function store()
    {
        $this->requireAuth();
        $clientModel = new Client();
        $data = [
            'full_name' => trim($_POST['full_name']),
            'phone' => $_POST['phone'] ?? null,
            'email' => $_POST['email'] ?? null
        ];
        $clientModel->create($data);
        $this->redirect('/clients');
    }

    /**
     * Show deposit form for a client
     * @param int $clientId
     */
    public function depositForm(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();
        $client = $clientModel->find($clientId);
        if (!$client) {
            $this->redirect('/clients');
        }
        $this->render('clients/deposit', ['client' => $client]);
    }

    /**
     * Process a deposit
     * @param int $clientId
     */
    public function deposit(int $clientId)
    {
        $this->requireAuth();

        $clientModel = new Client();
        $client = $clientModel->find($clientId);
        if (!$client) {
            $this->redirect('/clients');
        }

        $deposit = new Deposit();
        $data = [
            'client_id' => $clientId,
            'amount' => $_POST['amount'],
            'reference' => $_POST['reference'] ?? '',
            'payment_method' => $_POST['payment_method'],
            'deposit_date' => date('Y-m-d H:i:s'),
            'recorded_by' => $_SESSION['user_id'],
            'notes' => $_POST['notes'] ?? ''
        ];

        try {
            $deposit->create($data);

            // Refresh client balance
            $client = $clientModel->find($clientId);

            // Send email notification if client has email
            if (!empty($client['email'])) {
                $this->sendDepositEmail($client, $data['amount']);
            }

            // Send SMS notification if client has phone
            if (!empty($client['phone'])) {
                $this->sendDepositSms($client, $data['amount']);
            }

            $_SESSION['success'] = 'Deposit recorded successfully.';
        } catch (\Exception $e) {
            $_SESSION['error'] = 'Failed to record deposit: ' . $e->getMessage();
        }

        $this->redirect('/clients');
    }

    /**
     * Show transaction form for a client
     * @param int $clientId
     */
    public function transactionForm(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();
        $client = $clientModel->find($clientId);
        if (!$client) {
            $this->redirect('/clients');
        }
        $this->render('clients/transaction', ['client' => $client]);
    }

    /**
     * Process a transaction (debit/credit)
     * @param int $clientId
     */
    public function transaction(int $clientId)
    {
        $this->requireAuth();

        $clientModel = new Client();
        $client = $clientModel->find($clientId);
        if (!$client) {
            $this->redirect('/clients');
        }

        $amount = floatval($_POST['amount']);
        $type = $_POST['type'];

        // Check overdraft limit for debit transactions
        if ($type === 'debit' && !$clientModel->canDebit($clientId, $amount)) {
            $_SESSION['error'] = 'Transaction exceeds overdraft limit of KES ' . number_format($client['overdraft_limit'], 2);
            $this->redirect('/clients/' . $clientId . '/transaction');
            return;
        }

        $trans = new ClientTransaction();
        $data = [
            'client_id' => $clientId,
            'transaction_type' => $type,
            'amount' => $amount,
            'description' => $_POST['description'],
            'reference' => $_POST['reference'] ?? '',
            'transaction_date' => date('Y-m-d H:i:s'),
            'recorded_by' => $_SESSION['user_id']
        ];

        try {
            $trans->create($data);
            $_SESSION['success'] = 'Transaction recorded successfully.';
        } catch (\Exception $e) {
            $_SESSION['error'] = 'Failed to record transaction: ' . $e->getMessage();
        }

        $this->redirect('/clients');
    }

    /**
     * Show overdraft settings form
     */
    public function overdraftForm(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();
        $client = $clientModel->find($clientId);
        if (!$client) {
            $this->redirect('/clients');
        }
        $this->render('clients/overdraft', ['client' => $client]);
    }

    /**
     * Update overdraft settings (limit only, no interest)
     */
    public function updateOverdraft(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();

        $limit = floatval($_POST['overdraft_limit']);

        $clientModel->updateOverdraftSettings($clientId, $limit);
        $_SESSION['success'] = 'Overdraft limit updated.';
        $this->redirect('/clients');
    }

    /**
     * Generate PDF statement for a client
     * @param int $clientId
     */
    public function statementPdf(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();
        $statement = $clientModel->getStatement($clientId);

        if (!$statement) {
            die("Client not found");
        }

        $html = $this->generateStatementHtml($statement);

        $options = new Options();
        $options->set('isHtml5ParserEnabled', true);
        $options->set('isRemoteEnabled', true);
        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'portrait');
        $dompdf->render();

        $filename = 'statement_' . $statement['client']['client_code'] . '_' . date('Ymd') . '.pdf';
        $dompdf->stream($filename, ['Attachment' => true]);
        exit;
    }

    /**
     * Generate Excel statement for a client
     * @param int $clientId
     */
    public function statementExcel(int $clientId)
    {
        $this->requireAuth();
        $clientModel = new Client();
        $statement = $clientModel->getStatement($clientId);

        if (!$statement) {
            die("Client not found");
        }

        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // Title
        $sheet->setCellValue('A1', 'CLIENT STATEMENT');
        $sheet->mergeCells('A1:F1');
        $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
        $sheet->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);

        // Client info
        $sheet->setCellValue('A2', 'Client: ' . $statement['client']['full_name']);
        $sheet->setCellValue('A3', 'Code: ' . $statement['client']['client_code']);
        $sheet->setCellValue('A4', 'Current Balance: ' . number_format($statement['current_balance'], 2) . ' KES');
        $sheet->mergeCells('A2:F2');
        $sheet->mergeCells('A3:F3');
        $sheet->mergeCells('A4:F4');

        // Headers
        $headers = ['Date', 'Type', 'Description/Ref', 'Amount (KES)', 'Balance (KES)', 'Notes'];
        $col = 'A';
        foreach ($headers as $header) {
            $sheet->setCellValue($col . '6', $header);
            $col++;
        }

        // Style headers
        $headerStyle = $sheet->getStyle('A6:F6');
        $headerStyle->getFont()->setBold(true);
        $headerStyle->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                    ->getStartColor()->setARGB('FFCCCCCC');
        $headerStyle->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);

        // Data rows
        $row = 7;
        foreach ($statement['entries'] as $entry) {
            $sheet->setCellValue('A' . $row, date('Y-m-d H:i', strtotime($entry['date'])));
            $sheet->setCellValue('B' . $row, $entry['type']);
            $sheet->setCellValue('C' . $row, $entry['reference'] ?? '');
            $sheet->setCellValue('D' . $row, $entry['amount']);
            $sheet->setCellValue('E' . $row, $entry['balance']);
            $sheet->setCellValue('F' . $row, $entry['notes'] ?? '');
            $row++;
        }

        // Format number columns
        $sheet->getStyle('D7:E' . ($row-1))->getNumberFormat()->setFormatCode('#,##0.00');

        // Add borders to data
        $dataRange = 'A6:F' . ($row-1);
        $sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);

        // Auto-size columns
        foreach (range('A','F') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        // Output
        $filename = 'statement_' . $statement['client']['client_code'] . '_' . date('Ymd') . '.xlsx';
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer = new Xlsx($spreadsheet);
        $writer->save('php://output');
        exit;
    }

    /**
     * Generate HTML for PDF statement
     * @param array $statement
     * @return string
     */
    private function generateStatementHtml(array $statement): string
    {
        $client = $statement['client'];
        $entries = $statement['entries'];
        $currentBalance = $statement['current_balance'];

        ob_start();
        ?>
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>Client Statement - <?= htmlspecialchars($client['full_name']) ?></title>
            <style>
                body { font-family: DejaVu Sans, sans-serif; font-size: 12px; }
                .header { text-align: center; margin-bottom: 20px; }
                .client-info { margin-bottom: 20px; }
                table { width: 100%; border-collapse: collapse; }
                th { background-color: #f2f2f2; }
                th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
                .amount { text-align: right; }
                .footer { margin-top: 20px; font-weight: bold; }
            </style>
        </head>
        <body>
            <div class="header">
                <h1>CLIENT STATEMENT</h1>
                <h2><?= htmlspecialchars($client['full_name']) ?> (<?= htmlspecialchars($client['client_code']) ?>)</h2>
            </div>
            <div class="client-info">
                <p><strong>Current Balance:</strong> <?= number_format($currentBalance, 2) ?> KES</p>
                <p><strong>Generated:</strong> <?= date('Y-m-d H:i:s') ?></p>
            </div>
            <table>
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Type</th>
                        <th>Description/Ref</th>
                        <th>Amount (KES)</th>
                        <th>Balance (KES)</th>
                        <th>Notes</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($entries as $e): ?>
                    <tr>
                        <td><?= date('Y-m-d H:i', strtotime($e['date'])) ?></td>
                        <td><?= htmlspecialchars($e['type']) ?></td>
                        <td><?= htmlspecialchars($e['reference'] ?? '') ?></td>
                        <td class="amount"><?= number_format($e['amount'], 2) ?></td>
                        <td class="amount"><?= number_format($e['balance'], 2) ?></td>
                        <td><?= htmlspecialchars($e['notes'] ?? '') ?></td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
            <div class="footer">
                <p>End of Statement</p>
            </div>
        </body>
        </html>
        <?php
        return ob_get_clean();
    }

    /**
     * Send deposit confirmation email
     * @param array $client
     * @param float $amount
     */
    private function sendDepositEmail(array $client, float $amount): void
    {
        try {
            $emailService = new EmailService();
            $subject = "Deposit Confirmation - Finance Manager";
            $body = "
                <h3>Dear {$client['full_name']},</h3>
                <p>Your deposit of <strong>KES " . number_format($amount, 2) . "</strong> has been received.</p>
                <p>Your new balance is <strong>KES " . number_format($client['balance'], 2) . "</strong>.</p>
                <p>Thank you for using our services.</p>
                <p>-- Finance Manager Team</p>
            ";
            $emailService->send($client['email'], $subject, $body);
        } catch (\Exception $e) {
            error_log("Email failed for client {$client['id']}: " . $e->getMessage());
        }
    }
    /**
 * Show a global form to record a transaction for any client
 */
public function createTransactionForm()
{
    $this->requireAuth();
    $clientModel = new Client();
    $clients = $clientModel->getAll();
    $this->render('clients/create_transaction', [
        'clients' => $clients,
        'pageTitle' => 'Quick Transaction'
    ]);
}

/**
 * Process a transaction from the global form
 */
public function storeTransaction()
{
    $this->requireAuth();

    $clientId = isset($_POST['client_id']) ? (int)$_POST['client_id'] : null;
    $newClientName = trim($_POST['new_client_name'] ?? '');

    // Priority: new client name overrides selection
    if ($newClientName !== '') {
        // Create a new client with just the name
        $clientModel = new Client();
        $newClientId = (int)$clientModel->create([
            'full_name' => $newClientName,
            'phone' => null,
            'email' => null
        ]);
        $clientId = $newClientId;
    }

    if (!$clientId) {
        $_SESSION['error'] = 'Please select a client or enter a new client name.';
        $this->redirect('/clients/transaction/create');
        return;
    }

    $clientModel = new Client();
    $client = $clientModel->find($clientId);
    if (!$client) {
        $_SESSION['error'] = 'Client not found.';
        $this->redirect('/clients/transaction/create');
        return;
    }

    $amount = floatval($_POST['amount']);
    $type = $_POST['type'];

    if ($type === 'debit' && !$clientModel->canDebit($clientId, $amount)) {
        $_SESSION['error'] = 'Transaction exceeds overdraft limit of KES ' . number_format($client['overdraft_limit'], 2);
        $this->redirect('/clients/transaction/create');
        return;
    }

    $trans = new ClientTransaction();
    $data = [
        'client_id' => $clientId,
        'transaction_type' => $type,
        'amount' => $amount,
        'description' => $_POST['description'],
        'reference' => $_POST['reference'] ?? '',
        'transaction_date' => date('Y-m-d H:i:s'),
        'recorded_by' => $_SESSION['user_id']
    ];

    try {
        $trans->create($data);
        $_SESSION['success'] = 'Transaction recorded successfully.';
    } catch (\Exception $e) {
        $_SESSION['error'] = 'Failed to record transaction: ' . $e->getMessage();
    }

    $this->redirect('/clients');
}

    /**
     * Send deposit confirmation SMS
     * @param array $client
     * @param float $amount
     */
    private function sendDepositSms(array $client, float $amount): void
    {
        try {
            $smsService = new SmsService();
            $message = "Dear {$client['full_name']}, your deposit of KES " . number_format($amount, 2) .
                       " has been received. New balance: KES " . number_format($client['balance'], 2) .
                       ". Finance Manager.";
            $smsService->send($client['phone'], $message);
        } catch (\Exception $e) {
            error_log("SMS failed for client {$client['id']}: " . $e->getMessage());
        }
    }
}