<?php
namespace Modules\Suppliers\Controllers;

use Core\Controller;
use Core\Auth;
use Modules\Suppliers\Models\SupplierModel;

class SupplierController extends Controller {
    private SupplierModel $model;

    public function __construct() {
        parent::__construct();
        $this->model = new SupplierModel();
    }

    public function index() {
        $this->requireAuth();
        $orgId = $this->scopedOrgId();
        $page = max(1, (int)$this->getGet('page', 1));
        $perPage = 20;
        $filters = [
            'search' => $this->getGet('search', ''),
            'status' => $this->getGet('status', ''),
        ];

        $suppliers = $this->model->getAllForOrg($orgId, $filters, $page, $perPage);
        $total = $this->model->countForOrg($orgId, $filters);
        $stats = $this->model->getStats($orgId);

        $paginationData = [
            'current_page' => $page,
            'total_pages' => (int)ceil($total / $perPage),
            'total_items' => $total,
            'url_pattern' => APP_URL . '/suppliers?' . http_build_query(array_filter($filters)) . '&page=',
        ];

        $this->render('suppliers/index', [
            'suppliers' => $suppliers,
            'stats' => $stats,
            'filters' => $filters,
            'isPlatformView' => $orgId === null,
            'paginationData' => $paginationData,
        ]);
    }

    public function create() {
        $this->requireAuth();
        if (Auth::orgId() === null) {
            $this->setFlash('error', 'Suppliers belong to an organization. Log in as an organization user to register one.');
            $this->redirect('/suppliers');
        }
        $this->render('suppliers/create');
    }

    public function store() {
        $this->requireAuth();
        if (!$this->validateCsrf()) {
            $this->setFlash('error', 'Invalid security token. Please try again.');
            $this->redirect('/suppliers/create');
        }
        if (Auth::orgId() === null) {
            $this->setFlash('error', 'Suppliers belong to an organization. Log in as an organization user to register one.');
            $this->redirect('/suppliers');
        }

        $data = $this->buildSupplierData($_POST);
        if (empty($data['company_name']) || empty($data['tin']) || empty($data['address']) ||
            empty($data['phone']) || empty($data['email']) || empty($data['contact_person_name']) ||
            empty($data['contact_person_phone']) || empty($data['contact_person_email'])) {
            $this->setFlash('error', 'Please fill in all required fields.');
            $this->redirect('/suppliers/create');
        }

        $data['org_id'] = Auth::orgId();
        $data['created_by'] = Auth::id();
        $data['supplier_code'] = $this->model->generateSupplierCode();

        $supplierId = $this->model->create($data);

        $userFirstName = trim($_POST['user_first_name'] ?? '');
        $userLastName = trim($_POST['user_last_name'] ?? '');
        $userEmail = trim($_POST['user_email'] ?? '');
        if ($userFirstName && $userLastName && $userEmail) {
            $this->createPrimaryUser($supplierId, $data['company_name'], $userFirstName, $userLastName, $userEmail);
        }

        logAudit('supplier_created', 'suppliers', 'supplier', $supplierId, null, $data);
        $this->setFlash('success', 'Supplier registered successfully. Awaiting approval.');
        $this->redirect('/suppliers/' . $supplierId);
    }

    public function show($id) {
        $this->requireAuth();
        $supplier = $this->model->getWithDetails((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }

        $this->render('suppliers/show', [
            'supplier' => $supplier,
            'stats' => $this->model->getSupplierStats((int)$id),
            'documents' => $this->model->getDocuments((int)$id),
            'users' => $this->model->getUsers((int)$id),
            'invoices' => $this->model->getInvoices((int)$id),
            'projects' => [],
        ]);
    }

    public function edit($id) {
        $this->requireAuth();
        $supplier = $this->model->getWithDetails((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }
        $this->render('suppliers/create', ['supplier' => $supplier]);
    }

    public function update($id) {
        $this->requireAuth();
        if (!$this->validateCsrf()) {
            $this->setFlash('error', 'Invalid security token. Please try again.');
            $this->redirect('/suppliers/' . $id . '/edit');
        }

        $supplier = $this->model->find((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }

        $data = $this->buildSupplierData($_POST);
        $this->model->update((int)$id, $data);

        logAudit('supplier_updated', 'suppliers', 'supplier', (int)$id, $supplier, $data);
        $this->setFlash('success', 'Supplier updated successfully.');
        $this->redirect('/suppliers/' . $id);
    }

    public function approve($id) {
        $this->requireAuth();
        $supplier = $this->model->find((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }
        $this->model->update((int)$id, ['is_approved' => 1]);
        logAudit('supplier_approved', 'suppliers', 'supplier', (int)$id);
        $this->setFlash('success', 'Supplier approved.');
        $this->redirect('/suppliers/' . $id);
    }

    public function suspend($id) {
        $this->requireAuth();
        $supplier = $this->model->find((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }
        $this->model->update((int)$id, ['is_active' => 0]);
        logAudit('supplier_suspended', 'suppliers', 'supplier', (int)$id);
        $this->setFlash('success', 'Supplier suspended.');
        $this->redirect('/suppliers/' . $id);
    }

    public function uploadDocument($id) {
        $this->requireAuth();
        $supplier = $this->model->find((int)$id);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }

        if (!empty($_FILES['documents']) && !empty($_FILES['documents']['name'][0])) {
            $types = $_POST['document_types'] ?? [];
            $count = count($_FILES['documents']['name']);
            for ($i = 0; $i < $count; $i++) {
                if ($_FILES['documents']['error'][$i] !== UPLOAD_ERR_OK) {
                    continue;
                }
                $fileInput = [
                    'name' => $_FILES['documents']['name'][$i],
                    'type' => $_FILES['documents']['type'][$i],
                    'tmp_name' => $_FILES['documents']['tmp_name'][$i],
                    'error' => $_FILES['documents']['error'][$i],
                    'size' => $_FILES['documents']['size'][$i],
                ];
                $upload = $this->uploadFile($fileInput, 'supplier_docs');
                if (!$upload) {
                    continue;
                }
                $this->dbExecute(
                    "INSERT INTO supplier_documents (supplier_id, document_type, document_name, file_path, file_size, uploaded_by, created_at)
                     VALUES (?, ?, ?, ?, ?, ?, NOW())",
                    [(int)$id, $types[$i] ?? 'other', $upload['name'], $upload['path'], $upload['size'], Auth::id()]
                );
            }
        }

        $this->setFlash('success', 'Document uploaded successfully.');
        $this->redirect('/suppliers/' . $id);
    }

    public function deleteDocument($docId) {
        $this->requireAuth();
        $doc = $this->dbQueryOne("SELECT * FROM supplier_documents WHERE id = ?", [(int)$docId]);
        if (!$doc) {
            $this->setFlash('error', 'Document not found.');
            $this->redirect('/suppliers');
        }
        $supplier = $this->model->find((int)$doc['supplier_id']);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Document not found.');
            $this->redirect('/suppliers');
        }
        $this->dbExecute("DELETE FROM supplier_documents WHERE id = ?", [(int)$docId]);
        $this->setFlash('success', 'Document deleted.');
        $this->redirect('/suppliers/' . $doc['supplier_id']);
    }

    public function addUser($supplierId) {
        $this->requireAuth();
        if (!$this->validateCsrf()) {
            $this->setFlash('error', 'Invalid security token. Please try again.');
            $this->redirect('/suppliers/' . $supplierId);
        }
        $supplier = $this->model->find((int)$supplierId);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }

        $firstName = trim($_POST['first_name'] ?? '');
        $lastName = trim($_POST['last_name'] ?? '');
        $email = trim($_POST['email'] ?? '');
        if (!$firstName || !$lastName || !$email) {
            $this->setFlash('error', 'First name, last name, and email are required.');
            $this->redirect('/suppliers/' . $supplierId);
        }

        $this->createPrimaryUser((int)$supplierId, $supplier['company_name'], $firstName, $lastName, $email, !empty($_POST['is_admin']));
        $this->setFlash('success', 'User added successfully.');
        $this->redirect('/suppliers/' . $supplierId);
    }

    public function removeUser($supplierId, $userId) {
        $this->requireAuth();
        $supplier = $this->model->find((int)$supplierId);
        if (!$supplier || (int)$supplier['org_id'] !== (int)Auth::orgId()) {
            $this->setFlash('error', 'Supplier not found.');
            $this->redirect('/suppliers');
        }
        $this->dbExecute("DELETE FROM supplier_users WHERE supplier_id = ? AND user_id = ?", [(int)$supplierId, (int)$userId]);
        $this->dbExecute("UPDATE users SET is_active = 0 WHERE id = ? AND entity_type = 'supplier_user' AND entity_id = ?", [(int)$userId, (int)$supplierId]);
        $this->setFlash('success', 'User removed.');
        $this->redirect('/suppliers/' . $supplierId);
    }

    private function buildSupplierData(array $post): array {
        return [
            'company_name' => trim($post['company_name'] ?? ''),
            'tin' => trim($post['tin'] ?? ''),
            'address' => trim($post['address'] ?? ''),
            'phone' => trim($post['phone'] ?? ''),
            'email' => trim($post['email'] ?? ''),
            'website' => normalizeUrl($post['website'] ?? null),
            'categories' => $post['categories'] ?? null,
            'contact_person_name' => trim($post['contact_name'] ?? ''),
            'contact_person_phone' => trim($post['contact_phone'] ?? ''),
            'contact_person_email' => trim($post['contact_email'] ?? ''),
            'bank_name' => $post['bank_name'] ?? null,
            'account_number' => $post['account_number'] ?? null,
            'account_name' => $post['account_name'] ?? null,
        ];
    }

    private function createPrimaryUser(int $supplierId, string $companyName, string $firstName, string $lastName, string $email, bool $isAdmin = true): void {
        $existing = $this->dbQueryOne("SELECT id FROM users WHERE email = ?", [$email]);
        if ($existing) {
            $userId = (int)$existing['id'];
        } else {
            $tempPassword = substr(bin2hex(random_bytes(6)), 0, 10);
            $stmt = $this->db->prepare(
                "INSERT INTO users (org_id, entity_type, entity_id, first_name, last_name, email, password, is_active, created_at, updated_at)
                 VALUES (?, 'supplier_user', ?, ?, ?, ?, ?, 1, NOW(), NOW())"
            );
            $stmt->execute([Auth::orgId(), $supplierId, $firstName, $lastName, $email, password_hash($tempPassword, PASSWORD_BCRYPT)]);
            $userId = (int)$this->db->lastInsertId();

            $htmlBody = "<p>Hello {$firstName},</p><p>An account has been created for you to access {$companyName}'s projects on " . APP_NAME . ".</p>" .
                "<p>Email: {$email}<br>Temporary Password: {$tempPassword}</p>" .
                "<p><a href=\"" . APP_URL . "/login\">Login here</a> and change your password after signing in.</p>";
            sendEmail($email, $firstName . ' ' . $lastName, 'Your ' . APP_NAME . ' account', $htmlBody);
        }

        $exists = $this->dbQueryOne("SELECT id FROM supplier_users WHERE supplier_id = ? AND user_id = ?", [$supplierId, $userId]);
        if (!$exists) {
            $this->dbExecute(
                "INSERT INTO supplier_users (supplier_id, user_id, is_admin, created_at) VALUES (?, ?, ?, NOW())",
                [$supplierId, $userId, $isAdmin ? 1 : 0]
            );
        }
        createNotification($userId, 'account_created', 'Welcome to ' . APP_NAME, 'Your supplier account has been created.');
    }
}
