<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Response;
use App\Models\CustomerModel;
use App\Models\AuditLogModel;
use App\Helpers\GSTHelper;

/**
 * Customer Management Controller
 */
class CustomerController extends Controller
{
    private CustomerModel $customerModel;
    private AuditLogModel $auditLogger;

    public function __construct()
    {
        $this->customerModel = new CustomerModel();
        $this->auditLogger = new AuditLogModel();
    }

    /**
     * GET /api/v1/customers
     */
    public function index(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $filters = [
            'search' => $_GET['search'] ?? null,
            'status' => $_GET['status'] ?? 'active',
            'sort' => $_GET['sort'] ?? 'name',
            'order' => $_GET['order'] ?? 'ASC'
        ];
        $page = (int) ($_GET['page'] ?? 1);
        $perPage = (int) ($_GET['per_page'] ?? 20);

        $customers = $this->customerModel->getAll($tenantId, $filters, $page, $perPage);
        $total = $this->customerModel->countAll($tenantId, $filters);

        Response::paginated($customers, $total, $page, $perPage, "Customers retrieved successfully");
    }

    /**
     * POST /api/v1/customers
     */
    public function store(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $rawData = $this->getJsonBody();

        // Convert empty strings to null for strict typed validations and DB compliance
        $data = [];
        foreach ($rawData as $key => $value) {
            if (is_array($value)) {
                $data[$key] = $value;
            } else {
                $data[$key] = trim((string)($value ?? '')) === '' ? null : $value;
            }
        }

        $this->validate($data, [
            'display_name' => 'required|min:2|max:255',
            'email' => 'email',
            'credit_limit' => 'numeric',
            'payment_terms' => 'numeric',
            'opening_balance' => 'numeric'
        ]);

        // GSTIN Validation
        if (!empty($data['gstin'])) {
            $gstResult = GSTHelper::validate($data['gstin']);
            if ($gstResult['valid']) {
                $data['billing_state_code'] = $gstResult['state_code'];
                $data['billing_state'] = $gstResult['state_name'];
            }
        }

        // Professional field mapping
        $payload = [
            'tenant_id' => $tenantId,
            'created_by' => $userId,
            'customer_type' => $data['customer_type'] ?? 'business',
            'salutation' => $data['salutation'] ?? null,
            'first_name' => $data['first_name'] ?? null,
            'last_name' => $data['last_name'] ?? null,
            'name' => $data['display_name'], // map display_name to legacy name for safety
            'display_name' => $data['display_name'],
            'company_name' => $data['company_name'] ?? null,
            'email' => $data['email'] ?? null,
            'work_phone' => $data['work_phone'] ?? null,
            'mobile_phone' => $data['mobile_phone'] ?? null,
            'gstin' => $data['gstin'] ?? null,
            'pan' => $data['pan'] ?? null,
            'website' => $data['website'] ?? null,
            'currency' => $data['currency'] ?? 'INR',
            'payment_terms' => $data['payment_terms'] ?? 30,
            'credit_limit' => $data['credit_limit'] ?? 0.00,
            'opening_balance' => $data['opening_balance'] ?? 0.00,
            'opening_balance_type' => $data['opening_balance_type'] ?? 'debit',
            'portal_enabled' => (int)($data['portal_enabled'] ?? 0),
            'portal_language' => $data['portal_language'] ?? 'English',
            'department' => $data['department'] ?? null,
            'designation' => $data['designation'] ?? null,
            'twitter' => $data['twitter'] ?? null,
            'skype' => $data['skype'] ?? null,
            'facebook' => $data['facebook'] ?? null,
            'remarks' => $data['remarks'] ?? null,
            'notes' => $data['notes'] ?? null,
            
            // Addresses
            'billing_attention' => $data['billing_attention'] ?? null,
            'billing_country' => $data['billing_country'] ?? null,
            'billing_address' => $data['billing_street1'] ?? null, // Street 1
            'billing_city' => $data['billing_city'] ?? null,
            'billing_state' => $data['billing_state'] ?? null,
            'billing_state_code' => $data['billing_state_code'] ?? null,
            'billing_pincode' => $data['billing_pincode'] ?? null,
            'billing_phone' => $data['billing_phone'] ?? null,
            'billing_fax' => $data['billing_fax'] ?? null,

            'shipping_attention' => $data['shipping_attention'] ?? null,
            'shipping_country' => $data['shipping_country'] ?? null,
            'shipping_address' => $data['shipping_street1'] ?? null,
            'shipping_city' => $data['shipping_city'] ?? null,
            'shipping_state' => $data['shipping_state'] ?? null,
            'shipping_pincode' => $data['shipping_pincode'] ?? null,
            'shipping_phone' => $data['shipping_phone'] ?? null,
            'shipping_fax' => $data['shipping_fax'] ?? null,
            'shipping_same_as_billing' => (int)($data['shipping_same_as_billing'] ?? 0)
        ];

        $id = $this->customerModel->create($payload);

        if ($id) {
            if (!empty($data['contacts'])) {
                $this->customerModel->saveContacts((int)$id, $tenantId, $data['contacts']);
            }
            $this->auditLogger->log($tenantId, $userId, 'create', 'customers', (int) $id, null, $payload);
            Response::success(['id' => $id], 'Customer created successfully', 201);
        }

        Response::error('Failed to create customer');
    }

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

        if (!$customer) {
            Response::error('Customer not found', [], 404);
        }

        Response::success($customer);
    }

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

        $data = [];
        foreach ($rawData as $key => $value) {
            if (is_array($value)) {
                $data[$key] = $value;
            } else {
                $data[$key] = trim((string)($value ?? '')) === '' ? null : $value;
            }
        }

        $old = $this->customerModel->getById((int) $id, $tenantId);
        if (!$old) Response::error('Customer not found', [], 404);

        $this->validate($data, [
            'display_name' => 'required|min:2|max:255'
        ]);

        // GSTIN Validation
        if (!empty($data['gstin'])) {
            $gstResult = GSTHelper::validate($data['gstin']);
            if ($gstResult['valid']) {
                $data['billing_state_code'] = $gstResult['state_code'];
                $data['billing_state'] = $gstResult['state_name'];
            }
        }

        $payload = [
            'customer_type' => $data['customer_type'] ?? 'business',
            'salutation' => $data['salutation'] ?? null,
            'first_name' => $data['first_name'] ?? null,
            'last_name' => $data['last_name'] ?? null,
            'name' => $data['display_name'],
            'display_name' => $data['display_name'],
            'company_name' => $data['company_name'] ?? null,
            'email' => $data['email'] ?? null,
            'work_phone' => $data['work_phone'] ?? null,
            'mobile_phone' => $data['mobile_phone'] ?? null,
            'gstin' => $data['gstin'] ?? null,
            'pan' => $data['pan'] ?? null,
            'website' => $data['website'] ?? null,
            'currency' => $data['currency'] ?? 'INR',
            'payment_terms' => $data['payment_terms'] ?? 30,
            'credit_limit' => $data['credit_limit'] ?? 0.00,
            'opening_balance' => $data['opening_balance'] ?? 0.00,
            'opening_balance_type' => $data['opening_balance_type'] ?? 'debit',
            'portal_enabled' => (int)($data['portal_enabled'] ?? 0),
            'portal_language' => $data['portal_language'] ?? 'English',
            'department' => $data['department'] ?? null,
            'designation' => $data['designation'] ?? null,
            'twitter' => $data['twitter'] ?? null,
            'skype' => $data['skype'] ?? null,
            'facebook' => $data['facebook'] ?? null,
            'remarks' => $data['remarks'] ?? null,
            'notes' => $data['notes'] ?? null,
            
            'billing_attention' => $data['billing_attention'] ?? null,
            'billing_country' => $data['billing_country'] ?? null,
            'billing_address' => $data['billing_street1'] ?? null,
            'billing_city' => $data['billing_city'] ?? null,
            'billing_state' => $data['billing_state'] ?? null,
            'billing_state_code' => $data['billing_state_code'] ?? null,
            'billing_pincode' => $data['billing_pincode'] ?? null,
            'billing_phone' => $data['billing_phone'] ?? null,
            'billing_fax' => $data['billing_fax'] ?? null,

            'shipping_attention' => $data['shipping_attention'] ?? null,
            'shipping_country' => $data['shipping_country'] ?? null,
            'shipping_address' => $data['shipping_street1'] ?? null,
            'shipping_city' => $data['shipping_city'] ?? null,
            'shipping_state' => $data['shipping_state'] ?? null,
            'shipping_pincode' => $data['shipping_pincode'] ?? null,
            'shipping_phone' => $data['shipping_phone'] ?? null,
            'shipping_fax' => $data['shipping_fax'] ?? null,
            'shipping_same_as_billing' => (int)($data['shipping_same_as_billing'] ?? 0)
        ];

        if ($this->customerModel->update((int) $id, $payload)) {
            $this->customerModel->saveContacts((int)$id, $tenantId, $data['contacts'] ?? []);
            $this->auditLogger->log($tenantId, $userId, 'update', 'customers', (int) $id, $old, $payload);
            Response::success([], 'Customer updated successfully');
        }

        Response::error('Update failed');
    }

    /**
     * DELETE /api/v1/customers/{id}
     */
    public function destroy(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];

        if ($this->customerModel->softDelete((int) $id, $tenantId, $userId)) {
            Response::success([], 'Customer deactivated successfully');
        }

        Response::error('Delete failed or record not found');
    }

    /**
     * POST /api/v1/customers/validate-gstin
     */
    public function validateGstin(): void
    {
        $data = $this->getJsonBody();
        if (empty($data['gstin']))
            Response::error('GSTIN required');

        $result = GSTHelper::validate($data['gstin']);
        Response::success($result);
    }

    /**
     * POST /api/v1/customers/import
     */
    public function import(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];

        if (empty($_FILES['file']))
            Response::error('No file uploaded');

        $file = $_FILES['file']['tmp_name'];
        $handle = fopen($file, "r");
        $headers = fgetcsv($handle); // Read header row

        $rows = [];
        while (($data = fgetcsv($handle)) !== FALSE) {
            $rows[] = array_combine(['name', 'company', 'gstin', 'pan', 'email', 'phone', 'address'], array_slice($data, 0, 7));
        }
        fclose($handle);

        $result = $this->customerModel->import($tenantId, $userId, $rows);
        Response::success($result, "Import completed");
    }

    /**
     * GET /api/v1/customers/export
     */
    public function export(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $customers = $this->customerModel->getAll($tenantId, ['per_page' => 1000]);

        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="customers.csv"');

        $output = fopen('php://output', 'w');
        fputcsv($output, ['Name', 'Customer Type', 'Company', 'GSTIN', 'Email', 'Phone', 'Status']);

        foreach ($customers as $c) {
            fputcsv($output, [$c['name'], $c['customer_type'] ?? 'business', $c['company_name'], $c['gstin'], $c['email'], $c['phone'], $c['status']]);
        }
        fclose($output);
        exit;
    }
}
