<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Expenses extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->library('auth_lib');
        $this->load->library('form_validation');
        $this->load->model('Expense_model');
        $this->load->model('Cashbox_model');
        $this->load->helper(['url', 'form', 'text']);
        $this->auth_lib->require_login();
    }

    public function index()
    {
        $this->auth_lib->require_permission('expense_view');

        $filters = [
            'status'      => $this->input->get('status'),
            'location_id' => $this->input->get('location_id'),
            'category_id' => $this->input->get('category_id'),
            'date_from'   => $this->input->get('date_from'),
            'date_to'     => $this->input->get('date_to'),
            'search'      => $this->input->get('search'),
        ];

        if ( ! $this->auth_lib->is_manager_or_admin() && $this->auth_lib->location_id()) {
            $filters['user_location_id'] = $this->auth_lib->location_id();
        }

        $page   = max(1, (int) $this->input->get('page'));
        $limit  = 20;
        $offset = ($page - 1) * $limit;

        $this->load->model('User_model');

        $data = [
            'title'      => 'Gestion des Dépenses',
            'expenses'   => $this->Expense_model->get_list($filters, $limit, $offset),
            'total'      => $this->Expense_model->count_list($filters),
            'categories' => $this->Expense_model->get_categories(),
            'locations'  => $this->User_model->get_locations(),
            'filters'    => $filters,
            'page'       => $page,
            'limit'      => $limit,
        ];

        $this->load->view('templates/header', $data);
        $this->load->view('expenses/index', $data);
        $this->load->view('templates/footer');
    }

    public function create()
    {
        $this->auth_lib->require_permission('expense_create');

        $this->load->model('User_model');
        $this->load->model('Request_model');

        $cashboxes = $this->Cashbox_model->get_accessible(
            $this->auth_lib->location_id(),
            $this->auth_lib->is_manager_or_admin()
        );

        $data = [
            'title'             => 'Nouvelle Dépense',
            'categories'        => $this->Expense_model->get_categories(),
            'locations'         => $this->User_model->get_locations(),
            'cashboxes'         => $cashboxes,
            'approved_requests' => $this->Request_model->get_approved_unlinked(
                $this->auth_lib->is_manager_or_admin() ? null : $this->auth_lib->location_id()
            ),
        ];

        if ($this->input->method() === 'post') {
            $this->form_validation->set_rules('expense_date', 'Date', 'required');
            $this->form_validation->set_rules('operation_date', 'Date d\'opération', 'required');
            $this->form_validation->set_rules('category_id', 'Catégorie', 'required|integer');
            $this->form_validation->set_rules('location_id', 'Localisation', 'required|integer');
            $this->form_validation->set_rules('supplier', 'Fournisseur', 'required|trim|max_length[120]');
            $this->form_validation->set_rules('description', 'Description', 'required|trim');
            $this->form_validation->set_rules('amount', 'Montant', 'required|numeric|greater_than[0]');
            $this->form_validation->set_rules('cashbox_id', 'Caisse', 'required|integer');

            if ($this->form_validation->run() === TRUE) {
                $location_id = $this->input->post('location_id');
                $location = $this->db->where('id', $location_id)->get('locations')->row();

                $expense_data = [
                    'expense_id'     => $this->Expense_model->next_expense_id($location->code),
                    'expense_date'   => $this->input->post('expense_date'),
                    'operation_date' => $this->input->post('operation_date'),
                    'category_id'    => $this->input->post('category_id'),
                    'location_id'    => $location_id,
                    'cashbox_id'     => $this->input->post('cashbox_id'),
                    'request_id'     => $this->input->post('request_id') ?: null,
                    'supplier'       => $this->input->post('supplier', TRUE),
                    'description'    => $this->input->post('description', TRUE),
                    'amount'         => $this->input->post('amount'),
                    'currency'       => 'KMF',
                    'invoice_number' => $this->input->post('invoice_number', TRUE) ?: null,
                    'status'         => 'pending',
                    'created_by'     => $this->auth_lib->user_id(),
                ];

                // Upload facture
                if ( ! empty($_FILES['invoice_file']['name'])) {
                    $upload_path = './uploads/invoices/';
                    if ( ! is_dir($upload_path)) mkdir($upload_path, 0777, TRUE);

                    $this->load->library('upload', [
                        'upload_path'   => $upload_path,
                        'allowed_types' => 'jpg|jpeg|png',
                        'max_size'      => 5120,
                        'file_name'     => $expense_data['expense_id'] . '_' . time(),
                    ]);

                    if ($this->upload->do_upload('invoice_file')) {
                        $expense_data['invoice_path'] = 'uploads/invoices/' . $this->upload->data('file_name');
                    }
                }

                // Vérifier les doublons
                $duplicates = $this->Expense_model->check_duplicates($expense_data);

                $new_id = $this->Expense_model->create($expense_data);

                // Si demande liée, mettre à jour son statut
                if ($expense_data['request_id']) {
                    $this->load->model('Request_model');
                    $this->Request_model->update($expense_data['request_id'], ['status' => 'paid']);
                }

                $this->auth_lib->log_action(
                    $this->auth_lib->user_id(), 'expense_created', 'expenses', $new_id,
                    $expense_data['expense_id'] . ' | ' . number_format($expense_data['amount']) . ' KMF'
                );

                $msg = 'Dépense ' . $expense_data['expense_id'] . ' créée.';
                if ( ! empty($duplicates)) {
                    $msg .= ' ⚠️ ATTENTION : ' . count($duplicates) . ' doublon(s) potentiel(s) détecté(s) !';
                    $this->session->set_flashdata('warning', $msg);
                } else {
                    $this->session->set_flashdata('success', $msg);
                }

                redirect('expenses/view/' . $new_id);
            }
        }

        $this->load->view('templates/header', $data);
        $this->load->view('expenses/form', $data);
        $this->load->view('templates/footer');
    }

    /**
     * Créer une dépense directement depuis une demande approuvée
     * Pré-remplit et lie automatiquement
     */
    public function create_from_request($request_id)
    {
        $this->auth_lib->require_permission('expense_create');

        $this->load->model('Request_model');
        $this->load->model('User_model');

        $request = $this->Request_model->get($request_id);
        if ( ! $request || $request->status !== 'approved') {
            $this->session->set_flashdata('error', 'Demande introuvable ou non approuvée.');
            redirect('requests');
        }

        // Vérifier qu'aucune dépense n'est déjà liée
        $existing = $this->db->where('request_id', $request_id)->get('expenses')->row();
        if ($existing) {
            $this->session->set_flashdata('error', 'Une dépense est déjà liée à cette demande : ' . $existing->expense_id);
            redirect('expenses/view/' . $existing->id);
        }

        $cashboxes = $this->Cashbox_model->get_accessible(
            $this->auth_lib->location_id(),
            $this->auth_lib->is_manager_or_admin()
        );

        $data = [
            'title'      => 'Dépense pour ' . $request->reference,
            'request'    => $request,
            'categories' => $this->Expense_model->get_categories(),
            'locations'  => $this->User_model->get_locations(),
            'cashboxes'  => $cashboxes,
        ];

        if ($this->input->method() === 'post') {
            $this->form_validation->set_rules('expense_date', 'Date', 'required');
            $this->form_validation->set_rules('operation_date', 'Date d\'opération', 'required');
            $this->form_validation->set_rules('supplier', 'Fournisseur', 'required|trim|max_length[120]');
            $this->form_validation->set_rules('description', 'Description', 'required|trim');
            $this->form_validation->set_rules('amount', 'Montant', 'required|numeric|greater_than[0]');
            $this->form_validation->set_rules('cashbox_id', 'Caisse', 'required|integer');

            if ($this->form_validation->run() === TRUE) {
                $location = $this->db->where('id', $request->location_id)->get('locations')->row();

                $expense_data = [
                    'expense_id'     => $this->Expense_model->next_expense_id($location->code),
                    'expense_date'   => $this->input->post('expense_date'),
                    'operation_date' => $this->input->post('operation_date'),
                    'category_id'    => $request->category_id,
                    'location_id'    => $request->location_id,
                    'cashbox_id'     => $this->input->post('cashbox_id'),
                    'request_id'     => $request_id,
                    'supplier'       => $this->input->post('supplier', TRUE),
                    'description'    => $this->input->post('description', TRUE),
                    'amount'         => $this->input->post('amount'),
                    'currency'       => 'KMF',
                    'invoice_number' => $this->input->post('invoice_number', TRUE) ?: null,
                    'status'         => 'pending',
                    'created_by'     => $this->auth_lib->user_id(),
                ];

                // Upload facture
                if ( ! empty($_FILES['invoice_file']['name'])) {
                    $upload_path = './uploads/invoices/';
                    if ( ! is_dir($upload_path)) mkdir($upload_path, 0777, TRUE);

                    $this->load->library('upload', [
                        'upload_path'   => $upload_path,
                        'allowed_types' => 'jpg|jpeg|png|pdf',
                        'max_size'      => 5120,
                        'file_name'     => $expense_data['expense_id'] . '_' . time(),
                    ]);

                    if ($this->upload->do_upload('invoice_file')) {
                        $expense_data['invoice_path'] = 'uploads/invoices/' . $this->upload->data('file_name');
                    }
                }

                $new_id = $this->Expense_model->create($expense_data);

                // Mettre à jour le statut de la demande
                $this->Request_model->update($request_id, ['status' => 'paid']);

                $this->auth_lib->log_action(
                    $this->auth_lib->user_id(), 'expense_created', 'expenses', $new_id,
                    $expense_data['expense_id'] . ' | depuis ' . $request->reference . ' | ' . number_format($expense_data['amount']) . ' KMF'
                );

                $this->session->set_flashdata('success', 
                    'Dépense ' . $expense_data['expense_id'] . ' créée et liée à ' . $request->reference);
                redirect('expenses/view/' . $new_id);
            }
        }

        $this->load->view('templates/header', $data);
        $this->load->view('expenses/form_from_request', $data);
        $this->load->view('templates/footer');
    }

    public function view($id)
    {
        $this->auth_lib->require_permission('expense_view');

        $expense = $this->Expense_model->get($id);
        if ( ! $expense) show_404();

        if ( ! $this->auth_lib->can_access_location($expense->location_id)) {
            $this->session->set_flashdata('error', 'Accès refusé.');
            redirect('expenses');
        }

        $data = [
            'title'   => 'Dépense ' . $expense->expense_id,
            'expense' => $expense,
        ];

        $this->load->view('templates/header', $data);
        $this->load->view('expenses/view', $data);
        $this->load->view('templates/footer');
    }

    public function edit($id)
    {
        $this->auth_lib->require_permission('expense_edit');

        $expense = $this->Expense_model->get($id);
        if ( ! $expense) show_404();

        if ( ! in_array($expense->status, ['draft', 'pending'])) {
            $this->session->set_flashdata('error', 'Cette dépense ne peut plus être modifiée.');
            redirect('expenses/view/' . $id);
        }

        $this->load->model('User_model');

        $data = [
            'title'      => 'Modifier ' . $expense->expense_id,
            'expense'    => $expense,
            'categories' => $this->Expense_model->get_categories(),
            'locations'  => $this->User_model->get_locations(),
            'cashboxes'  => $this->Cashbox_model->get_accessible(
                $this->auth_lib->location_id(), $this->auth_lib->is_manager_or_admin()
            ),
        ];

        if ($this->input->method() === 'post') {
            $this->form_validation->set_rules('expense_date', 'Date', 'required');
            $this->form_validation->set_rules('operation_date', 'Date d\'opération', 'required');
            $this->form_validation->set_rules('category_id', 'Catégorie', 'required|integer');
            $this->form_validation->set_rules('supplier', 'Fournisseur', 'required|trim');
            $this->form_validation->set_rules('description', 'Description', 'required|trim');
            $this->form_validation->set_rules('amount', 'Montant', 'required|numeric|greater_than[0]');

            if ($this->form_validation->run() === TRUE) {
                $update_data = [
                    'expense_date'   => $this->input->post('expense_date'),
                    'operation_date' => $this->input->post('operation_date'),
                    'category_id'    => $this->input->post('category_id'),
                    'supplier'       => $this->input->post('supplier', TRUE),
                    'description'    => $this->input->post('description', TRUE),
                    'amount'         => $this->input->post('amount'),
                    'invoice_number' => $this->input->post('invoice_number', TRUE) ?: null,
                    'cashbox_id'     => $this->input->post('cashbox_id'),
                ];

                if ( ! empty($_FILES['invoice_file']['name'])) {
                    $upload_path = './uploads/invoices/';
                    if ( ! is_dir($upload_path)) mkdir($upload_path, 0777, TRUE);

                    $this->load->library('upload', [
                        'upload_path'   => $upload_path,
                        'allowed_types' => 'jpg|jpeg|png|pdf',
                        'max_size'      => 5120,
                        'file_name'     => $expense->expense_id . '_' . time(),
                    ]);

                    if ($this->upload->do_upload('invoice_file')) {
                        $update_data['invoice_path'] = 'uploads/invoices/' . $this->upload->data('file_name');
                    }
                }

                $this->Expense_model->update($id, $update_data);

                $this->auth_lib->log_action(
                    $this->auth_lib->user_id(), 'expense_updated', 'expenses', $id, $expense->expense_id
                );

                $this->session->set_flashdata('success', 'Dépense modifiée.');
                redirect('expenses/view/' . $id);
            }
        }

        $this->load->view('templates/header', $data);
        $this->load->view('expenses/edit_form', $data);
        $this->load->view('templates/footer');
    }

    public function validate($id)
    {
        $this->auth_lib->require_permission('expense_validate');

        $expense = $this->Expense_model->get($id);
        if ( ! $expense) show_404();

        $success = $this->Expense_model->validate_expense($id, $this->auth_lib->user_id());

        if ($success) {
            $this->auth_lib->log_action(
                $this->auth_lib->user_id(), 'expense_validated', 'expenses', $id,
                $expense->expense_id . ' | ' . number_format($expense->amount) . ' KMF'
            );
            $this->session->set_flashdata('success', 
                'Dépense ' . $expense->expense_id . ' validée. La caisse a été débitée.');
        } else {
            $this->session->set_flashdata('error', 'Impossible de valider cette dépense.');
        }

        redirect('expenses/view/' . $id);
    }

    public function reject($id)
    {
        $this->auth_lib->require_permission('expense_validate');

        $expense = $this->Expense_model->get($id);
        if ( ! $expense) show_404();

        $reason = $this->input->post('rejection_reason', TRUE);
        if (empty($reason)) {
            $this->session->set_flashdata('error', 'Veuillez indiquer un motif de rejet.');
            redirect('expenses/view/' . $id);
        }

        $this->Expense_model->reject_expense($id, $this->auth_lib->user_id(), $reason);

        $this->auth_lib->log_action(
            $this->auth_lib->user_id(), 'expense_rejected', 'expenses', $id,
            $expense->expense_id . ' | Motif: ' . $reason
        );

        $this->session->set_flashdata('success', 'Dépense rejetée.');
        redirect('expenses/view/' . $id);
    }
}
