<?php
// ============================================================
//  MJPOS – Fingerprint Upload Controller
// ============================================================
class FPUploadController extends Controller
{
    public function index(): void
    {
        Auth::requireLogin();
        $pageTitle  = 'Fingerprint Data Uploader';
        $breadcrumb = [
            ['label'=>'Payroll','url'=>APP_URL.'/payroll'],
            ['label'=>'FP Data Upload'],
        ];
        ob_start(); require APP_PATH.'/views/payroll/fp_upload.php';
        $content = ob_get_clean();
        require APP_PATH.'/views/layouts/main.php';
    }

    public function template(): void
    {
        Auth::requireLogin();
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="fingerprint_template.csv"');
        $out = fopen('php://output','w');
        fputcsv($out,['UserID','Date','Time','Status','DeviceID']);
        try {
            $emps = Database::fetchAll(
                "SELECT fingerprint_id,emp_code,full_name FROM employees WHERE status='active' ORDER BY emp_code"
            );
            foreach ($emps as $e) {
                fputcsv($out,[$e['fingerprint_id']?:$e['emp_code'],date('Y-m-d'),'08:00:00','0','ZK-DEVICE-01']);
                fputcsv($out,[$e['fingerprint_id']?:$e['emp_code'],date('Y-m-d'),'17:00:00','1','ZK-DEVICE-01']);
            }
        } catch(Exception $e) {
            fputcsv($out,['FP001',date('Y-m-d'),'08:00:00','0','ZK-DEVICE-01']);
            fputcsv($out,['FP001',date('Y-m-d'),'17:00:00','1','ZK-DEVICE-01']);
        }
        fclose($out); exit;
    }

    public function import(): void
    {
        Auth::requireLogin();
        Auth::requireCsrf();
        header('Content-Type: application/json');

        $rows = json_decode($this->post('rows','[]'), true);
        $imported = 0; $errors = 0;

        foreach ((array)$rows as $row) {
            $fpId = trim($row['empId'] ?? '');
            $date = $this->parseDate(trim($row['date'] ?? ''));
            $time = trim($row['time'] ?? '') ?: null;
            $type = $row['type'] ?? 'in';

            if (!$fpId || !$date) { $errors++; continue; }

            try {
                $emp = Database::fetchOne(
                    "SELECT id FROM employees WHERE (fingerprint_id=? OR emp_code=?) AND status='active'",
                    [$fpId,$fpId]
                );
                if (!$emp) { $errors++; continue; }

                $existing = Database::fetchOne(
                    'SELECT * FROM employee_attendance WHERE employee_id=? AND att_date=?',
                    [$emp['id'],$date]
                );

                if ($type === 'in') {
                    if (!$existing) {
                        Database::execute(
                            "INSERT INTO employee_attendance (employee_id,att_date,check_in,status,method,fingerprint_id,recorded_by)
                             VALUES (?,?,?,'present','fingerprint',?,?)",
                            [$emp['id'],$date,$time,$fpId,Auth::id()]
                        );
                    } elseif (!$existing['check_in']) {
                        Database::execute(
                            "UPDATE employee_attendance SET check_in=?,method='fingerprint',fingerprint_id=? WHERE id=?",
                            [$time,$fpId,$existing['id']]
                        );
                    }
                } elseif ($type === 'out' && $existing) {
                    $inTs  = $existing['check_in'] ? strtotime($date.' '.$existing['check_in']) : 0;
                    $outTs = $time ? strtotime($date.' '.$time) : 0;
                    $wh    = ($inTs&&$outTs) ? round(min(max(0,($outTs-$inTs)/3600),12),2) : 0;
                    $oth   = round(max(0,$wh-9),2);
                    Database::execute(
                        'UPDATE employee_attendance SET check_out=?,worked_hours=?,ot_hours=? WHERE id=?',
                        [$time,$wh,$oth,$existing['id']]
                    );
                }

                // Log to fingerprint_logs if table exists
                try {
                    if ($time) {
                        Database::execute(
                            "INSERT INTO fingerprint_logs (device_id,device_user_id,employee_id,punch_time,punch_type,status)
                             VALUES ('IMPORT',?,?,?,'$type','processed')",
                            [$fpId,$emp['id'],$date.' '.$time]
                        );
                    }
                } catch(Exception $e) {}

                $imported++;
            } catch(Exception $e) { $errors++; }
        }

        try { Auth::logAudit(Auth::id(),'fp_import','attendance',"FP import: {$imported} records, {$errors} errors"); } catch(Exception $e){}
        echo json_encode(['imported'=>$imported,'errors'=>$errors]);
        exit;
    }

    private function parseDate(string $raw): string
    {
        if (!$raw) return '';
        foreach (['Y-m-d','d/m/Y','m/d/Y','d-m-Y','Ymd','d M Y','Y/m/d'] as $fmt) {
            $dt = \DateTime::createFromFormat($fmt, $raw);
            if ($dt) return $dt->format('Y-m-d');
        }
        $ts = strtotime($raw);
        return $ts ? date('Y-m-d',$ts) : '';
    }
    // ── Attendance Chart ──────────────────────────────────────
    public function chart(): void
    {
        Auth::requireLogin();

        $month = (int)$this->get('month', date('n'));
        $year  = (int)$this->get('year',  date('Y'));
        $monthLabel   = date('F Y', mktime(0,0,0,$month,1,$year));
        $daysInMonth  = cal_days_in_month(CAL_GREGORIAN,$month,$year);
        $monthStart   = sprintf('%04d-%02d-01',$year,$month);
        $monthEnd     = sprintf('%04d-%02d-%02d',$year,$month,$daysInMonth);

        // Count actual working days (exclude Sundays)
        $workingDays = 0;
        for($d=1;$d<=$daysInMonth;$d++) {
            if(date('w',mktime(0,0,0,$month,$d,$year)) != 0) $workingDays++;
        }

        // All active employees
        $employees = Database::fetchAll(
            "SELECT id,emp_code,full_name,fingerprint_id FROM employees WHERE status='active' ORDER BY full_name"
        );
        $totalEmployees = count($employees);

        // Per-employee stats
        $empStats = Database::fetchAll(
            "SELECT e.id,e.emp_code,e.full_name,e.fingerprint_id,
                    COUNT(CASE WHEN ea.status='present' THEN 1 END) AS present,
                    COUNT(CASE WHEN ea.status='absent'  THEN 1 END) AS absent,
                    COUNT(CASE WHEN ea.status='late'    THEN 1 END) AS late,
                    COUNT(CASE WHEN ea.status='leave'   THEN 1 END) AS leave_days,
                    COUNT(CASE WHEN ea.status='half_day'THEN 1 END) AS half_day,
                    COALESCE(SUM(ea.ot_hours),0)     AS ot_hours,
                    COALESCE(SUM(ea.worked_hours),0) AS worked_hours
             FROM employees e
             LEFT JOIN employee_attendance ea
               ON ea.employee_id=e.id AND ea.att_date BETWEEN ? AND ?
             WHERE e.status='active'
             GROUP BY e.id ORDER BY e.full_name",
            [$monthStart,$monthEnd]
        );

        // Totals
        $totalPresent   = array_sum(array_column($empStats,'present'));
        $totalAbsent    = array_sum(array_column($empStats,'absent'));
        $totalLate      = array_sum(array_column($empStats,'late'));
        $totalLeave     = array_sum(array_column($empStats,'leave_days'));
        $totalHalfDay   = array_sum(array_column($empStats,'half_day'));
        $totalOT        = array_sum(array_column($empStats,'ot_hours'));
        $totalWorkedHrs = array_sum(array_column($empStats,'worked_hours'));

        // FP count
        try {
            $fpCount = (int)Database::fetchColumn(
                "SELECT COUNT(*) FROM employee_attendance
                 WHERE method='fingerprint' AND att_date BETWEEN ? AND ?",
                [$monthStart,$monthEnd]
            );
        } catch(Exception $e) { $fpCount = 0; }

        // Daily data for trend chart
        $dailyRaw = Database::fetchAll(
            "SELECT att_date,
                    COUNT(CASE WHEN status='present' THEN 1 END) AS present,
                    COUNT(CASE WHEN status='absent'  THEN 1 END) AS absent,
                    COUNT(CASE WHEN status='late'    THEN 1 END) AS late,
                    COUNT(CASE WHEN status='leave'   THEN 1 END) AS leave_days
             FROM employee_attendance
             WHERE att_date BETWEEN ? AND ? AND status != 'off'
             GROUP BY att_date ORDER BY att_date",
            [$monthStart,$monthEnd]
        );
        $dailyMap = [];
        foreach($dailyRaw as $r) {
            $dailyMap[$r['att_date']] = $r;
        }
        $dailyData = [];
        for($d=1;$d<=$daysInMonth;$d++) {
            $dow = date('w',mktime(0,0,0,$month,$d,$year));
            if($dow == 0) continue; // skip Sunday
            $dt  = sprintf('%04d-%02d-%02d',$year,$month,$d);
            $rec = $dailyMap[$dt] ?? ['present'=>0,'absent'=>0,'late'=>0,'leave_days'=>0];
            $dailyData[] = [
                'day'     => $d.'\n'.date('D',mktime(0,0,0,$month,$d,$year)),
                'present' => (int)$rec['present'],
                'absent'  => (int)$rec['absent'],
                'late'    => (int)$rec['late'],
                'leave'   => (int)($rec['leave_days'] ?? 0),
            ];
        }

        // Status breakdown for doughnut
        $statusData = [
            ['label'=>'Present', 'value'=>$totalPresent],
            ['label'=>'Absent',  'value'=>$totalAbsent],
            ['label'=>'Late',    'value'=>$totalLate],
            ['label'=>'Leave',   'value'=>$totalLeave],
            ['label'=>'Half Day','value'=>$totalHalfDay],
        ];

        // Method breakdown
        $methodRaw = Database::fetchAll(
            "SELECT method, COUNT(*) AS cnt FROM employee_attendance
             WHERE att_date BETWEEN ? AND ? AND status NOT IN ('off','absent')
             GROUP BY method ORDER BY cnt DESC",
            [$monthStart,$monthEnd]
        );
        $methodLabels = ['fingerprint'=>'Fingerprint','manual'=>'Manual','qr'=>'QR Code','card'=>'Card','face'=>'Face'];
        $methodData = array_map(fn($r)=>[
            'label' => $methodLabels[$r['method']]??ucfirst($r['method']),
            'value' => (int)$r['cnt'],
        ], $methodRaw);

        // OT data (top 10 by OT hours)
        $otData = array_map(fn($e)=>[
            'name'  => explode(' ',$e['full_name'])[0],
            'hours' => (float)$e['ot_hours'],
        ], array_filter($empStats,fn($e)=>$e['ot_hours']>0));
        usort($otData,fn($a,$b)=>$b['hours']<=>$a['hours']);
        $otData = array_slice($otData,0,10);

        $pageTitle  = 'Attendance Analytics — '.$monthLabel;
        $breadcrumb = [
            ['label'=>'Payroll','url'=>APP_URL.'/payroll'],
            ['label'=>'Attendance Analytics'],
        ];
        ob_start(); require APP_PATH.'/views/payroll/attendance_chart.php';
        $content = ob_get_clean();
        require APP_PATH.'/views/layouts/main.php';
    }

}