<?php

class TimeRecord {
    private $pdo;
    
    public function __construct() {
        try {
            $this->pdo = new PDO(
                'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8',
                DB_USER,
                DB_PASS,
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
        } catch (PDOException $e) {
            throw new Exception('Erro na conexão com o banco de dados: ' . $e->getMessage());
        }
    }
    
    /**
     * Registra entrada do colaborador
     */
    public function clockIn($employeeId, $notes = null) {
        // Verifica se já existe entrada sem saída no dia
        $today = date('Y-m-d');
        $existingRecord = $this->getTodayRecord($employeeId);
        
        if ($existingRecord && !$existingRecord['exit_time']) {
            throw new Exception('Já existe um registro de entrada sem saída para hoje');
        }
        
        $sql = "INSERT INTO time_records (employee_id, work_date, entry_time, notes, created_at) 
                VALUES (:employee_id, :work_date, :entry_time, :notes, NOW())";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':employee_id' => $employeeId,
            ':work_date' => $today,
            ':entry_time' => date('H:i:s'),
            ':notes' => $notes
        ]);
        
        return $this->pdo->lastInsertId();
    }
    
    /**
     * Registra saída do colaborador
     */
    public function clockOut($employeeId, $notes = null) {
        $today = date('Y-m-d');
        $record = $this->getTodayRecord($employeeId);
        
        if (!$record) {
            throw new Exception('Não foi encontrado registro de entrada para hoje');
        }
        
        if ($record['exit_time']) {
            throw new Exception('Saída já foi registrada para hoje');
        }
        
        $exitTime = date('H:i:s');
        $totalHours = $this->calculateHoursWorked($record['entry_time'], $exitTime);
        
        $sql = "UPDATE time_records 
                SET exit_time = :exit_time, 
                    total_hours = :total_hours, 
                    notes = CONCAT(COALESCE(notes, ''), :notes),
                    updated_at = NOW()
                WHERE id = :id";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':exit_time' => $exitTime,
            ':total_hours' => $totalHours,
            ':notes' => $notes ? ' | Saída: ' . $notes : '',
            ':id' => $record['id']
        ]);
        
        return $record['id'];
    }
    
    /**
     * Registra início de pausa
     */
    public function startBreak($employeeId, $notes = null) {
        $today = date('Y-m-d');
        $record = $this->getTodayRecord($employeeId);
        
        if (!$record || !$record['clock_in'] || $record['clock_out']) {
            throw new Exception('Não é possível iniciar pausa sem registro de entrada válido');
        }
        
        if ($record['break_start'] && !$record['break_end']) {
            throw new Exception('Já existe uma pausa em andamento');
        }
        
        $sql = "UPDATE time_records 
                SET break_start = :break_start,
                    notes = CONCAT(COALESCE(notes, ''), :notes),
                    updated_at = NOW()
                WHERE id = :id";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':break_start' => date('H:i:s'),
            ':notes' => $notes ? ' | Início pausa: ' . $notes : '',
            ':id' => $record['id']
        ]);
        
        return $record['id'];
    }
    
    /**
     * Registra fim de pausa
     */
    public function endBreak($employeeId, $notes = null) {
        $today = date('Y-m-d');
        $record = $this->getTodayRecord($employeeId);
        
        if (!$record || !$record['break_start'] || $record['break_end']) {
            throw new Exception('Não foi encontrada pausa em andamento');
        }
        
        $breakEnd = date('H:i:s');
        $breakDuration = $this->calculateBreakDuration($record['break_start'], $breakEnd);
        
        $sql = "UPDATE time_records 
                SET break_end = :break_end,
                    break_duration = :break_duration,
                    notes = CONCAT(COALESCE(notes, ''), :notes),
                    updated_at = NOW()
                WHERE id = :id";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':break_end' => $breakEnd,
            ':break_duration' => $breakDuration,
            ':notes' => $notes ? ' | Fim pausa: ' . $notes : '',
            ':id' => $record['id']
        ]);
        
        return $record['id'];
    }
    
    /**
     * Busca registro do dia atual
     */
    public function getTodayRecord($employeeId) {
        $sql = "SELECT * FROM time_records 
                WHERE employee_id = :employee_id AND work_date = :work_date
                ORDER BY created_at DESC LIMIT 1";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':employee_id' => $employeeId,
            ':work_date' => date('Y-m-d')
        ]);
        
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Busca registros por período
     */
    public function getRecordsByPeriod($employeeId, $startDate, $endDate) {
        $sql = "SELECT tr.*, e.full_name as employee_name, e.job_title AS position
                FROM time_records tr
                JOIN employees e ON tr.employee_id = e.id
                WHERE tr.employee_id = :employee_id 
                AND tr.work_date BETWEEN :start_date AND :end_date
                ORDER BY tr.work_date DESC, tr.created_at DESC";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':employee_id' => $employeeId,
            ':start_date' => $startDate,
            ':end_date' => $endDate
        ]);
        
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Busca todos os registros de um colaborador
     */
    public function getEmployeeRecords($employeeId, $limit = 50, $offset = 0) {
        $sql = "SELECT * FROM time_records 
                WHERE employee_id = :employee_id
                ORDER BY work_date DESC, created_at DESC
                LIMIT :limit OFFSET :offset";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindValue(':employee_id', $employeeId, PDO::PARAM_INT);
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();
        
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Busca registros de todos os colaboradores por data
     */
    public function getAllRecordsByDate($date) {
        $sql = "SELECT tr.*, e.full_name as employee_name, e.job_title AS position
                FROM time_records tr
                JOIN employees e ON tr.employee_id = e.id
                WHERE tr.work_date = :work_date
                ORDER BY e.full_name, tr.created_at";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':work_date' => $date]);
        
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Calcula horas trabalhadas
     */
    private function calculateHoursWorked($clockIn, $clockOut, $breakDuration = 0) {
        $start = new DateTime($clockIn);
        $end = new DateTime($clockOut);
        
        $totalMinutes = ($end->getTimestamp() - $start->getTimestamp()) / 60;
        $workedMinutes = $totalMinutes - $breakDuration;
        
        return round($workedMinutes / 60, 2);
    }
    
    /**
     * Calcula duração da pausa em minutos
     */
    private function calculateBreakDuration($breakStart, $breakEnd) {
        $start = new DateTime($breakStart);
        $end = new DateTime($breakEnd);
        
        return ($end->getTimestamp() - $start->getTimestamp()) / 60;
    }
    
    /**
     * Relatório de horas por colaborador
     */
    public function getHoursReport($employeeId, $month, $year) {
        $sql = "SELECT 
                    COUNT(*) as total_days,
                    SUM(total_hours) as total_hours,
                    AVG(total_hours) as avg_hours_per_day,
                    SUM(CASE WHEN total_hours >= 8 THEN 1 ELSE 0 END) as full_days,
                    0 as total_break_minutes
                FROM time_records 
                WHERE employee_id = :employee_id 
                AND MONTH(work_date) = :month 
                AND YEAR(work_date) = :year
                AND exit_time IS NOT NULL";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':employee_id' => $employeeId,
            ':month' => $month,
            ':year' => $year
        ]);
        
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Verifica status atual do colaborador
     */
    public function getCurrentStatus($employeeId) {
        $record = $this->getTodayRecord($employeeId);
        
        if (!$record) {
            return 'not_clocked_in';
        }
        
        if ($record['exit_time']) {
            return 'clocked_out';
        }
        
        return 'working';
    }
    
    /**
     * Formata tempo para exibição
     */
    public static function formatTime($time) {
        if (!$time) return '-';
        return date('H:i', strtotime($time));
    }
    
    /**
     * Formata duração em minutos para horas:minutos
     */
    public static function formatDuration($minutes) {
        if (!$minutes) return '00:00';
        
        $hours = floor($minutes / 60);
        $mins = $minutes % 60;
        
        return sprintf('%02d:%02d', $hours, $mins);
    }
}