<?php

namespace Modules\Customers\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Session;
use core\Security;
use Modules\Customers\Models\Customer;

class CustomerController extends Controller
{
    private Customer $customerModel;

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

    public function index(): void
    {
        $this->requirePermission('customers_view');

        $search = $this->request->get('search', '');
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;
        $db = Database::getInstance();

        $query = $db->table('customers c')
            ->select('c.*,
                (SELECT COUNT(*) FROM appointments a WHERE a.customer_id = c.id AND a.deleted_at IS NULL) as total_visits,
                (SELECT COALESCE(SUM(i.grand_total), 0) FROM invoices i WHERE i.customer_id = c.id AND i.deleted_at IS NULL) as total_spent,
                (SELECT MAX(a.start_time) FROM appointments a WHERE a.customer_id = c.id AND a.deleted_at IS NULL) as last_visit')
            ->where('c.deleted_at', 'IS', null);

        if (!empty($search)) {
            $query->where(function($q) use ($search) {
                $q->where('c.first_name', 'LIKE', '%' . $search . '%')
                  ->orWhere('c.last_name', 'LIKE', '%' . $search . '%')
                  ->orWhere('c.email', 'LIKE', '%' . $search . '%')
                  ->orWhere('c.phone', 'LIKE', '%' . $search . '%');
            });
        }

        $customers = $query->orderBy('c.created_at', 'DESC')
            ->paginate($perPage, $page);

        $this->view('Customers/index', [
            'title' => 'Customers',
            'breadcrumb' => ['Customers' => url('customers')],
            'customers' => $customers,
            'search' => $search,
        ]);
    }

    public function create(): void
    {
        $this->requirePermission('customers_create');

        $this->view('Customers/create', [
            'title' => 'Add New Customer',
            'breadcrumb' => [
                'Customers' => url('customers'),
                'Add New' => url('customers/create'),
            ],
        ]);
    }

    public function store(): void
    {
        $this->requirePermission('customers_create');

        $validated = $this->validate([
            'first_name' => 'required|max_length:100',
            'last_name' => 'required|max_length:100',
            'email' => 'email|max_length:255',
            'phone' => 'max_length:20',
            'mobile' => 'max_length:20',
            'date_of_birth' => 'date',
            'gender' => 'in:male,female,other',
            'address' => 'max_length:500',
            'city' => 'max_length:100',
            'state' => 'max_length:100',
            'zip' => 'max_length:20',
            'notes' => 'max_length:2000',
            'allergies' => 'max_length:2000',
            'source' => 'max_length:100',
        ]);

        $customerId = $this->customerModel->create($validated);
        $this->logActivity('create', 'Created customer: ' . ($validated['first_name'] ?? '') . ' ' . ($validated['last_name'] ?? ''));
        $this->logAudit('create', 'customers', $customerId, null, $validated);

        $this->redirectWith(url('customers'), 'success', 'Customer created successfully.');
    }

    public function edit(int $id): void
    {
        $this->requirePermission('customers_edit');

        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->redirectWith(url('customers'), 'error', 'Customer not found.');
        }

        $this->view('Customers/edit', [
            'title' => 'Edit Customer',
            'breadcrumb' => [
                'Customers' => url('customers'),
                'Edit' => url('customers/edit/' . $id),
            ],
            'customer' => $customer,
        ]);
    }

    public function update(int $id): void
    {
        $this->requirePermission('customers_edit');

        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->redirectWith(url('customers'), 'error', 'Customer not found.');
        }

        $oldValues = (array)$customer;

        $validated = $this->validate([
            'first_name' => 'required|max_length:100',
            'last_name' => 'required|max_length:100',
            'email' => 'email|max_length:255',
            'phone' => 'max_length:20',
            'mobile' => 'max_length:20',
            'date_of_birth' => 'date',
            'gender' => 'in:male,female,other',
            'address' => 'max_length:500',
            'city' => 'max_length:100',
            'state' => 'max_length:100',
            'zip' => 'max_length:20',
            'notes' => 'max_length:2000',
            'allergies' => 'max_length:2000',
            'hair_history' => 'max_length:2000',
            'skin_notes' => 'max_length:2000',
            'source' => 'max_length:100',
        ]);

        $this->customerModel->update($id, $validated);
        $this->logActivity('update', 'Updated customer: ' . ($validated['first_name'] ?? '') . ' ' . ($validated['last_name'] ?? ''));
        $this->logAudit('update', 'customers', $id, $oldValues, $validated);

        $this->redirectWith(url('customers'), 'success', 'Customer updated successfully.');
    }

    public function show(int $id): void
    {
        $this->requirePermission('customers_view');

        $db = Database::getInstance();
        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->redirectWith(url('customers'), 'error', 'Customer not found.');
        }

        $stats = $this->customerModel->getCustomerStats($id);

        $visits = $db->query(
            "SELECT a.*, GROUP_CONCAT(DISTINCT s.name SEPARATOR ', ') as service_names,
                    GROUP_CONCAT(DISTINCT CONCAT(e.first_name, ' ', e.last_name) SEPARATOR ', ') as employee_names
             FROM appointments a
             LEFT JOIN appointment_services aps ON a.id = aps.appointment_id
             LEFT JOIN services s ON aps.service_id = s.id
             LEFT JOIN employees e ON aps.employee_id = e.id
             WHERE a.customer_id = :customer_id AND a.deleted_at IS NULL
             GROUP BY a.id
             ORDER BY a.start_time DESC",
            [':customer_id' => $id]
        );

        $invoices = $db->table('invoices')
            ->where('customer_id', $id)
            ->where('deleted_at', 'IS', null)
            ->orderBy('created_at', 'DESC')
            ->get();

        $photos = $db->table('customer_photos')
            ->where('customer_id', $id)
            ->orderBy('created_at', 'DESC')
            ->get();

        $notes = $db->table('customer_notes')
            ->select('customer_notes.*, u.first_name as user_first_name, u.last_name as user_last_name')
            ->leftJoin('users u', 'customer_notes.created_by', '=', 'u.id')
            ->where('customer_notes.customer_id', $id)
            ->orderBy('customer_notes.created_at', 'DESC')
            ->get();

        $membership = $db->table('customer_memberships')
            ->where('customer_id', $id)
            ->where('status', 'active')
            ->first();

        $loyaltyPoints = $db->table('loyalty_points')
            ->where('customer_id', $id)
            ->sum('balance');

        $this->view('Customers/show', [
            'title' => $customer->first_name . ' ' . $customer->last_name,
            'breadcrumb' => [
                'Customers' => url('customers'),
                $customer->first_name . ' ' . $customer->last_name => url('customers/show/' . $id),
            ],
            'customer' => $customer,
            'stats' => $stats,
            'visits' => $visits,
            'invoices' => $invoices,
            'photos' => $photos,
            'notes' => $notes,
            'membership' => $membership,
            'loyaltyPoints' => $loyaltyPoints,
        ]);
    }

    public function delete(int $id): void
    {
        $this->requirePermission('customers_delete');

        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->redirectWith(url('customers'), 'error', 'Customer not found.');
        }

        $this->customerModel->softDelete($id);
        $this->logActivity('delete', 'Deleted customer: ' . $customer->first_name . ' ' . $customer->last_name);
        $this->logAudit('delete', 'customers', $id, (array)$customer, null);

        $this->redirectWith(url('customers'), 'success', 'Customer deleted successfully.');
    }

    public function search(): void
    {
        $this->requirePermission('customers_view');

        $query = $this->request->get('q', '');
        $results = [];

        if (!empty($query)) {
            $results = $this->customerModel->search($query);
        }

        $html = '';
        if (!empty($results)) {
            ob_start();
            include PATH_MODULES . DS . 'Customers' . DS . 'Views' . DS . 'search_results.php';
            $html = ob_get_clean();
        }

        $this->json([
            'success' => true,
            'data' => $results,
            'html' => $html,
        ]);
    }

    public function uploadPhoto(int $id): void
    {
        $this->requirePermission('customers_edit');

        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->error('Customer not found.', 404);
        }

        if (!$this->request->hasFile('photo')) {
            $this->error('No file uploaded.', 400);
        }

        $file = $this->request->file('photo');
        $validation = Security::validateFile($file, ['jpg', 'jpeg', 'png', 'gif', 'webp'], UPLOAD_MAX_SIZE);
        if (!$validation['valid']) {
            $this->error('Invalid file.', 400, $validation['errors']);
        }

        $path = uploadFile($file, 'customers/' . $id);
        if (!$path) {
            $this->error('Failed to upload file.', 500);
        }

        $db = Database::getInstance();
        $db->table('customer_photos')->insert([
            'customer_id' => $id,
            'file_path' => $path,
            'original_name' => $file['name'],
            'uploaded_by' => Auth::id(),
            'created_at' => date(DATE_TIME_FORMAT),
        ]);

        $this->logActivity('upload_photo', 'Uploaded photo for customer: ' . $customer->first_name . ' ' . $customer->last_name);

        $this->success(['path' => uploadUrl($path)], 'Photo uploaded successfully.');
    }

    public function addNote(int $id): void
    {
        $this->requirePermission('customers_edit');

        $customer = $this->customerModel->find($id);
        if (!$customer) {
            $this->error('Customer not found.', 404);
        }

        $validated = $this->validate([
            'note' => 'required|max_length:5000',
        ]);

        $db = Database::getInstance();
        $noteId = $db->table('customer_notes')->insert([
            'customer_id' => $id,
            'user_id' => Auth::id(),
            'note' => $validated['note'],
            'created_at' => date(DATE_TIME_FORMAT),
            'updated_at' => date(DATE_TIME_FORMAT),
        ]);

        $this->logActivity('add_note', 'Added note for customer: ' . $customer->first_name . ' ' . $customer->last_name);

        $this->success(['note_id' => $noteId], 'Note added successfully.');
    }

    public function history(int $id): void
    {
        $this->requirePermission('customers_view');

        $db = Database::getInstance();
        $visits = $db->table('appointments a')
            ->select('a.*, s.name as service_name, s.duration, s.price,
                     e.first_name as employee_first_name, e.last_name as employee_last_name')
            ->leftJoin('services s', 'a.service_id', '=', 's.id')
            ->leftJoin('employees e', 'a.employee_id', '=', 'e.id')
            ->where('a.customer_id', $id)
            ->where('a.deleted_at', 'IS', null)
            ->orderBy('a.start_time', 'DESC')
            ->get();

        $this->json([
            'success' => true,
            'data' => $visits,
        ]);
    }
}
