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

// Manually require the autoload file from the library's directory
require_once APPPATH . 'third_party/escpos/autoload.php';

use Mike42\Escpos\Printer;
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;

class Tokens extends CI_Controller {

    private $printerName = "Black Copper BC-85AC"; // printer name

    public function __construct()
    {


        parent::__construct();



    // Get the called method
    $current_method = $this->router->fetch_method();

    // List of methods that can bypass session
    $public_methods = ['bill_print_view'];

    if (!in_array($current_method, $public_methods)) {
        if (!isset($_SESSION['qurbani_user_id'])) {
            redirect('/admin', 'refresh');
        }
    }

        // Load all required models
        $this->load->model('User_model', 'user');
        $this->load->model('Settings_model', 'setup');
        $this->load->model('Payment_model', 'payment');
        $this->load->model('Token_model', 'token');
        $this->load->model('Shifts_model', 'shifts');
        $this->load->model('Departments_model', 'departments');
        $this->load->model('Services_model', 'services');
        $this->load->model('Sub_services_model', 'sub_services');
        $this->load->model('Slip_settings_model', 'slipsetup');
        $this->load->helper('custom');

    }


    public function reports()
        {   
            $data['tokenwithshift'] = $this->token->getAllTokens(); 
            $data['settings'] = $this->setup->get_by_id(1);

            $data['breadcrumb'] = [
                ['label' => 'Tokens', 'url' => base_url('admin/tokens')],
                ['label' => 'Reports',   'url' => ''] // current page
            ];
            $data['title'] = 'Token';
            $data['mainContent'] = 'admin/tokens/reports';
            $this->load->view('admin/layout/master', $data);
        }




public function index()
{
    if (!$this->user->has_permission('tokens', 'view')) {
        redirect('/admin','refresh');
    }

    $data['shifts']       = $this->shifts->get_all();
    $data['departments']  = $this->departments->get_all();
    $data['services']     = $this->services->get_all();
    $data['sub_services'] = $this->sub_services->get_all();
    $data['service_fees'] = $this->db->get('kns1_service_fees')->result();
    $data['total_tokens_today'] = $this->token->count_today_tokens();
    $data['shift_tokens_today'] = $this->token->count_today_tokens_by_shift();
    $data['tokenwithshift'] = $this->token->getAllTokens();
    $data['settings'] = $this->setup->get_by_id(1);
$data['tokens_per_shift'] = $this->token->count_tokens_today_grouped_by_shift();
$data['tokens_per_department'] = $this->token->count_tokens_today_grouped_by_department();
// $data['tokens_per_department'] = $this->token->count_today_tokens_by_department();

$data['total_tokens_today'] = $this->token->count_today_tokens(); // you already have this

    // --- Add this code block to set shift and autoGeneratedToken ---
    $current_time   = date('H:i:s');
    $selected_shift = null;
    foreach ($data['shifts'] as $shift) {
        if (strtotime($current_time) >= strtotime($shift->start_time) &&
            strtotime($current_time) <= strtotime($shift->end_time)) {
            $selected_shift = $shift->id;
            $selectedShiftObj = $shift;  // Save object for view
            break;
        }
    }
    if (!$selected_shift && !empty($data['shifts'])) {
        $selected_shift = $data['shifts'][0]->id;
        $selectedShiftObj = $data['shifts'][0];
    }

    $last_token = $this->token->get_shift_tokens($selected_shift, date('Y-m-d'));
    $autoGeneratedToken = $last_token + 1;

    // Pass these variables to the view
    $data['selectedShiftObj'] = $selectedShiftObj ?? null;
    $data['selected_shift']   = $selected_shift; // add-token-form ko scalar shift id chahiye
    $data['autoGeneratedToken'] = $autoGeneratedToken;

    $data['breadcrumb'] = [
        ['label' => 'Tokens', 'url' => base_url('admin/tokens')],
        ['label' => 'All Tokens', 'url' => ''] // current page
    ];

 // Fetch raw stats from model
    $rawStats = $this->token->todayDepartmentStatsDynamic();
    $shifts   = $data['shifts'];

    // Build structured stats array
    $stats = [];

    foreach ($rawStats as $r) {
        // Department key setup
        if (!isset($stats[$r->department_id])) {
            $stats[$r->department_id] = [
                'department_name' => $r->department_name,
                'sponsors' => []
            ];
        }

        // Sponsor key setup
        if (!isset($stats[$r->department_id]['sponsors'][$r->funded_by])) {
            $stats[$r->department_id]['sponsors'][$r->funded_by] = [
                'funded_by' => $r->funded_by,
                'shifts' => [],
                'total_tokens' => 0,
                'total_amount' => 0,
                'total_discount' => 0,
                'total_refund' => 0,
                'net_total' => 0,
            ];
        }

        // Assign token count per shift
        $stats[$r->department_id]['sponsors'][$r->funded_by]['shifts'][$r->shift_id] = (int)$r->token_count;

        // Update totals per sponsor
        $sponsor =& $stats[$r->department_id]['sponsors'][$r->funded_by];

        $sponsor['total_tokens']   += $r->token_count;
        $sponsor['total_amount']   += $r->total_amount;
        $sponsor['total_discount'] += $r->total_discount;
        $sponsor['total_refund']   += $r->total_refund;
        $sponsor['net_total']      += ($r->total_amount - $r->total_discount - $r->total_refund);
    }

    $data['stats'] = $stats;

    // Initialize totals
    $totalTokens = 0;
    $totalAmount = 0;
    $totalNet    = 0;
    $totalDiscount = 0;
    $totalRefund   = 0;

    $totalFundedTokens = 0;
    $totalFundedAmount = 0;

    $deptChartLabels = [];
    $deptTokenData   = [];
    $deptNetData     = [];

    foreach ($stats as $dept) {

        $deptTokens = 0;
        $deptNet    = 0;

        foreach ($dept['sponsors'] as $sp) {
            $totalTokens += $sp['total_tokens'];
            $totalAmount += $sp['total_amount'];
            $totalNet    += $sp['net_total'];

            $deptTokens += $sp['total_tokens'];
            $deptNet    += $sp['net_total'];

            $totalDiscount += $sp['total_discount'];
            $totalRefund   += $sp['total_refund'];

            // Funded tokens and amount check (exclude self / walk-in)
            if (!empty($sp['funded_by']) && strtolower(trim($sp['funded_by'])) !== 'self / walk-in' && strtolower(trim($sp['funded_by'])) !== 'self') {
                $totalFundedTokens += $sp['total_tokens'];
                $totalFundedAmount += $sp['net_total'];
            }
        }

        $deptChartLabels[] = $dept['department_name'];
        $deptTokenData[]   = $deptTokens;
        $deptNetData[]     = $deptNet;
    }

    // Net cash = total net - funded amount
    $totalCash = $totalNet;

    // Pass all totals and charts to view
    $data['totalTokens'] = $totalTokens;
    $data['totalAmount'] = $totalAmount;
    $data['totalNet'] = $totalNet;
    $data['totalDiscount'] = $totalDiscount;
    $data['totalRefund'] = $totalRefund;

    $data['totalFundedTokens'] = $totalFundedTokens;
    $data['totalFundedAmount'] = $totalFundedAmount;
    $data['totalCash'] = $totalCash;

    $data['deptChartLabels'] = $deptChartLabels;
    $data['deptTokenData'] = $deptTokenData;
    $data['deptNetData'] = $deptNetData;





    $data['title'] = 'Token';
    $data['mainContent'] = 'admin/tokens/index';

    $this->load->view('admin/layout/master', $data);
}


public function add()
{
    // Permission check
    if (!$this->user->has_permission('tokens', 'add')) {
        redirect('/admin', 'refresh');
    }

    if ($_SERVER['REQUEST_METHOD'] == 'POST') {

        // --- Basic info ---
        $name      = $this->input->post('name');
        $phone     = $this->input->post('phone');
        $shift_id  = $this->input->post('shift_id');
        $gender    = $this->input->post('gender');
        $age       = $this->input->post('age');
        $age_unit  = $this->input->post('age_unit');
        $funded_by = $this->input->post('funded_by');
        $discount_percent = $this->input->post('discount_percent');
        $discount_amount  = $this->input->post('discount_amount');
        $date      = date('Y-m-d');

        // --- Token number for this shift/date ---
        $last_token = $this->token->get_shift_tokens($shift_id, $date);
        $new_token  = $last_token + 1;

        // --- Create token record ---
        $token_id = $this->token->create_token(
            $shift_id,
            $new_token,
            $name,
            $phone,
            $gender,
            $age,
            $age_unit,
            $funded_by,
            $discount_percent,
            $discount_amount
        );

        if ($token_id) {

            // --- Posted Services / Sub-services ---
            $posted_subs = array_values(array_unique(array_map('intval', (array)$this->input->post('sub_services'))));
            $posted_srvs = array_values(array_unique(array_map('intval', (array)$this->input->post('services'))));

            // 1) Insert Sub-services
            foreach ($posted_subs as $ss_id) {
                $ss = $this->db->get_where('kns1_sub_services', ['id' => $ss_id])->row();
                if (!$ss) continue;

                $service = $this->db->get_where('kns1_services', ['id' => $ss->service_id])->row();
                if (!$service) continue;

                $fee_row  = $this->db->get_where('kns1_service_fees', ['sub_service_id' => $ss_id])->row();
                $fee      = $fee_row ? (float)$fee_row->fee : 0.00;
                $currency = $fee_row ? $fee_row->currency : 'PKR';

                $this->db->insert('kns1_token_services', [
                    'token_id'       => $token_id,
                    'department_id'  => $service->department_id,
                    'service_id'     => $service->id,
                    'sub_service_id' => $ss->id,
                    'fee'            => $fee,
                    'currency'       => $currency
                ]);
            }

            // 2) Insert Services without sub-services
            foreach ($posted_srvs as $srv_id) {

                // skip if sub-services already selected for this service
                $found = $this->db->where_in('id', $posted_subs)
                                  ->where('service_id', $srv_id)
                                  ->get('kns1_sub_services')
                                  ->num_rows();
                if ($found > 0) continue;

                $service = $this->db->get_where('kns1_services', ['id' => $srv_id])->row();
                if (!$service) continue;

                // Get service fee without sub-service
                $fee_row  = $this->db->where('service_id', $srv_id)
                                     ->where('sub_service_id IS NULL', null, false)
                                     ->get('kns1_service_fees')
                                     ->row();
                $fee      = $fee_row ? (float)$fee_row->fee : 0.00;
                $currency = $fee_row ? $fee_row->currency : 'PKR';

                // Check if any sub-services exist; create default if none
                $sub_obj = $this->db->where('service_id', $srv_id)
                                    ->get('kns1_sub_services')
                                    ->row();
                if ($sub_obj) {
                    $sub_id_to_use = $sub_obj->id;
                } else {
                    $this->db->insert('kns1_sub_services', [
                        'service_id'  => $srv_id,
                        'name'        => $service->name . ' - Default',
                        'description' => 'Auto-created placeholder sub-service'
                    ]);
                    $sub_id_to_use = $this->db->insert_id();
                }

                $this->db->insert('kns1_token_services', [
                    'token_id'       => $token_id,
                    'department_id'  => $service->department_id,
                    'service_id'     => $service->id,
                    'sub_service_id' => $sub_id_to_use,
                    'fee'            => $fee,
                    'currency'       => $currency
                ]);
            }

            // 3) Calculate total fee
            $token_services = $this->db->get_where('kns1_token_services', ['token_id' => $token_id])->result();
            $total_amount = 0;
            foreach ($token_services as $ts) {
                $total_amount += (float)$ts->fee;
            }

            // Apply discount (never allow negative totals)
            $discount_amount        = max(0, (float)$discount_amount);
            $total_after_discount   = max(0, $total_amount - $discount_amount);

            // Paid amount from form
            $paid_amount = (float)$this->input->post('paid_amount');
            if ($paid_amount > $total_after_discount) {
                $paid_amount = $total_after_discount; // prevent over-payment
            }
            $balance = $total_after_discount - $paid_amount;

            // Update token with totals
            $this->db->where('id', $token_id)->update('kns1_tokens', [
                'total_fee' => $total_after_discount,
                'balance'   => $balance
            ]);

            // Insert Payment transaction (only if something paid)
            if ($paid_amount > 0) {
                $payment_data = [
                    'payment_module' => 'Token',
                    'module_id'      => $token_id,
                    'debit'          => $paid_amount, // amount received
                    'user_id'        => $_SESSION['qurbani_user_id'] ?? 1,
                    'created_at'     => date('Y-m-d H:i:s')
                ];
                $this->payment->create($payment_data);
            }

            $this->session->set_flashdata('message', "Token Created Successfully");
            redirect(base_url('admin/tokens/view/' . $token_id));

        } else {
            $this->session->set_flashdata('error', "Something Went Wrong! Please Try Again.");
            redirect(base_url('admin/tokens/add'));
        }
    }

    // --- GET: load form defaults ---
    $data['shifts']       = $this->shifts->get_all();
    $data['departments']  = $this->departments->get_all();
    $data['services']     = $this->services->get_all();
    $data['sub_services'] = $this->sub_services->get_all();
    $data['service_fees'] = $this->db->get('kns1_service_fees')->result();

    // auto-detect shift
    $current_time   = date('H:i:s');
    $selected_shift = null;
    foreach ($data['shifts'] as $shift) {
        if (strtotime($current_time) >= strtotime($shift->start_time) &&
            strtotime($current_time) <= strtotime($shift->end_time)) {
            $selected_shift = $shift->id;
            break;
        }
    }
    if (!$selected_shift && !empty($data['shifts'])) {
        $selected_shift = $data['shifts'][0]->id;
    }

    $last_token                 = $this->token->get_shift_tokens($selected_shift, date('Y-m-d'));
    $data['autoGeneratedToken'] = $last_token + 1;
    $data['selected_shift']     = $selected_shift;
    $data['settings']           = $this->setup->get_by_id(1);
    $data['breadcrumb'] = [
        ['label' => 'Tokens', 'url' => base_url('admin/tokens')],
        ['label' => 'Add New Token', 'url' => ''] // current page
    ];   
    $data['title']              = 'Add Token';
    $data['mainContent']        = 'admin/tokens/add';

    $this->load->view('admin/layout/master', $data);
}

public function apply_payment()
{

    // POST data
    $id     = $this->input->post('id');
    $amount = (float)$this->input->post('paid_amount');

    // Basic validation
    if (empty($id) || $amount <= 0) {
        $this->session->set_flashdata('error', 'Invalid payment data.');
        redirect($_SERVER['HTTP_REFERER'] ?? base_url('admin/tokens'));
        return;
    }

    // Get token
    $token = $this->token->get_by($id);
    if (!$token) {
        $this->session->set_flashdata('error', 'Token not found.');
        redirect(base_url('admin/tokens'));
        return;
    }

    $balance = (float)$token->balance;

    // Prevent overpayment
    $paid_amount = min($amount, $balance);

    if ($paid_amount <= 0) {
        $this->session->set_flashdata('error', 'Nothing to pay. Balance already cleared.');
        redirect(base_url('admin/tokens/view/' . $id));
        return;
    }

    // Insert into payments table
    $this->payment->create([
        'payment_module' => 'Token',
        'module_id'      => $id,
        'debit'          => $paid_amount, // received amount
        'credit'         => 0,
        'user_id'        => $_SESSION['qurbani_user_id'] ?? 1,
        'created_at'     => date('Y-m-d H:i:s')
    ]);

    // Update token balance
    $new_balance = $balance - $paid_amount;

    $this->db->where('id', $id)->update('kns1_tokens', [
        'balance' => $new_balance
    ]);

    // Success message
    $this->session->set_flashdata(
        'message',
        'Payment of ' . number_format($paid_amount, 2) . ' applied successfully.'
    );

    // Redirect back to token view
    redirect(base_url('admin/tokens/view/' . $id));
}





    public function view($id)
    {
                $data['SlipSettings'] = $this->slipsetup->get_by_id(1); // always id = 1

        $data['print_invoicing'] = $this->token->get_by($id);
        // 1. Token + Shift
        $data['tokenwithshift'] = $this->token->get_by($id);

        if ($data['tokenwithshift']) {

            // 2. Services for this token (with fee)
            $data['services'] = $this->token->get_services($id);

            // 3. Total amount row
            $data['total_row'] = $this->token->get_token_total($id);

// $new_balance = $this->apply_payment($id, $this->input->post('paid_amount'));

            // 4. Common view data
            $data['settings']   = $this->setup->get_by_id(1);
            $data['title']      = 'View Token';
            $data['breadcrumb'] = [
                ['label' => 'Tokens', 'url' => base_url('admin/tokens')],
                ['label' => 'View Token',   'url' => ''] // current page
            ];
            $data['mainContent']= 'admin/tokens/print';
            $this->load->view('admin/layout/master', $data);

        } else {
            echo "Token not found!";
        }
    }

    public function  bill_print_view($id)
    {
        $data['print_invoicing'] = $this->token->get_by($id);
            // 1. Token + Shift
            $data['tokenwithshift'] = $this->token->get_by($id);

            if ($data['tokenwithshift']) {

                // 2. Services for this token (with fee)
                $data['services'] = $this->token->get_services($id);

                // 3. Total amount row
                $data['total_row'] = $this->token->get_token_total($id);

                // 4. Common view data
                $data['settings']   = $this->setup->get_by_id(1);

                $this->load->view('admin/tokens/bill-print-view', $data);

            } else {
                echo "Token not found!";
            }
}

// function to print a Token slip








public function get_token_stats()
{
    $year  = $this->input->get('year') ?? date('Y');
    $month = $this->input->get('month') ?? date('m');

    // Daily breakdown by shift
    $this->db->select("DAY(t.created_at) as day, s.name as shift_name, COUNT(t.id) as token_count");
    $this->db->from("kns1_tokens t");
    $this->db->join("kns1_shifts s", "t.shift_id = s.id", "left");
    $this->db->where("YEAR(t.created_at)", $year);
    $this->db->where("MONTH(t.created_at)", $month);
    $this->db->group_by("DAY(t.created_at), s.id, s.name");
    $this->db->order_by("day", "asc");
    $daily = $this->db->get()->result();

    // Monthly breakdown (whole year by shift)
$this->db->select("YEAR(t.created_at) as year, MONTH(t.created_at) as month, s.name as shift_name, COUNT(t.id) as token_count");
$this->db->from("kns1_tokens t");
$this->db->join("kns1_shifts s", "t.shift_id = s.id", "left");
$this->db->where("YEAR(t.created_at)", $year);
$this->db->group_by("YEAR(t.created_at), MONTH(t.created_at), s.id, s.name");
$this->db->order_by("month", "asc");
$monthly = $this->db->get()->result();
    // Single clean JSON output
    $this->output
         ->set_content_type('application/json')
         ->set_output(json_encode([
             'daily'   => $daily,
             'monthly' => $monthly
         ]));
}















    public function edit()


{
    if ($this->input->post()) {
        $this->db->where('id', $this->input->post('id'));
        $update = $this->db->update('kns1_tokens', [
            'name'     => $this->input->post('name'),
            'phone'    => $this->input->post('phone'),
            'gender'   => $this->input->post('gender'),
            'age'      => $this->input->post('age'),
            'age_unit' => $this->input->post('age_unit')
        ]);

        if ($update) {
            $this->session->set_flashdata('message', 'Token updated successfully.');
        } else {
            $this->session->set_flashdata('error', 'Failed to update token. Please try again.');
        }
    }
    redirect('admin/tokens/index');
}



    // function to delete a Token
    public function delete($id)
    {
        $affected = $this->token->destroy($id);
        if($affected)
        {
            $data['message'] = "Token Deleted Successfully";
        }
        redirect(base_url().'admin/Tokens');
    }

// public function return_token($id)
// {
//     // check k token exist karta hai ya nahi
//     $token = $this->db->get_where('kns1_tokens', ['id' => $id])->row();
//     if (!$token) {
//         $this->session->set_flashdata('error', 'Token not found!');
//         redirect(base_url('admin/tokens'));
//         return;
//     }

//     // sari related payments wapis karni
//     $payments = $this->db->get_where('kns1_payment', [
//         'payment_module' => 'Token',
//         'module_id'      => $id
//     ])->result();

//     foreach ($payments as $p) {
//         $refund = [
//             'payment_module' => 'Token Return #' . $id,
//             'module_id'      => $id,
//             'credit'         => $p->debit,  // debit ka reverse
//             'user_id'        => $_SESSION['qurbani_user_id'] ?? 1,
//             'created_at'     => date('Y-m-d H:i:s')
//         ];
//         $this->db->insert('kns1_payment', $refund);
//     }

//     $this->session->set_flashdata('message', "Token #{$id} return hogya aur payments refund hogayi.");
//     redirect(base_url('admin/tokens'));
// }



public function return_token($id)
{
    // 1️⃣ Token check
    $token = $this->db->get_where('kns1_tokens', ['id' => $id])->row();

    if (!$token) {
        $this->session->set_flashdata('error', 'Token not found!');
        redirect(base_url('admin/tokens'));
        return;
    }

    // 2️⃣ Already returned protection
    if ($token->returned_at !== null) {
        $this->session->set_flashdata('error', 'Token already returned!');
        redirect(base_url('admin/tokens'));
        return;
    }

    // 3️⃣ Total paid amount (debit)
    $paid = $this->db->select('SUM(debit) as total_paid')
                     ->from('kns1_payment')
                     ->where('payment_module', 'Token')
                     ->where('module_id', $id)
                     ->get()
                     ->row()
                     ->total_paid ?? 0;

    if ($paid <= 0) {
        $this->session->set_flashdata('error', 'No payment found to refund!');
        redirect(base_url('admin/tokens'));
        return;
    }

    // 4️⃣ Refund payment entry
    $refund_payment = [
        'payment_module' => 'Token Return',
        'module_id'      => $id,
        'credit'         => $paid,
        'user_id'        => $_SESSION['qurbani_user_id'] ?? 1,
        'created_at'     => date('Y-m-d H:i:s')
    ];
    $this->db->insert('kns1_payment', $refund_payment);

    // 5️⃣ Update token refund fields
    $this->db->where('id', $id)->update('kns1_tokens', [
        'refund_amount' => $paid,
        'returned_at'   => date('Y-m-d H:i:s'),
        'balance'       => 0
    ]);

    // 6️⃣ Done
    $this->session->set_flashdata(
        'message',
        "Token #{$id} successfully returned. Refund Amount: PKR {$paid}"
    );

    redirect(base_url('admin/tokens'));
}



public function check_phone($phone = null)
{
    // Agar POST se nahi, to URL segment se phone lein
    if ($phone === null) {
        $phone = $this->input->post('phone');
    }

    if (!$phone) {
        echo json_encode(['status' => 'error', 'message' => 'Phone number missing']);
        return;
    }

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

    $result = $this->Token_model->get_by_phone($phone);

    if ($result) {
        echo json_encode([
            'status' => 'found',
            'name' => $result->name,
            'age' => $result->age,
            'gender' => $result->gender,
        ]);
    } else {
        echo json_encode(['status' => 'not_found']);
    }
}

public function get_sub_services_by_services()
{
    $method = $_SERVER['REQUEST_METHOD'];

    $input = $method === 'POST'
        ? json_decode($this->input->raw_input_stream, true)
        : $this->input->get();

    $service_ids = $input['service_ids'] ?? [];

    $sub_services = $this->sub_services->get_by_service_ids($service_ids);

    return $this->output
        ->set_content_type('application/json')
        ->set_output(json_encode([
            'method' => $method,
            'sub_services' => $sub_services
        ]));
}







}