<?php
require_once 'config/database.php';

class AppointmentsController {
    private $conn;

    public function __construct() {
        $database = new Database();
        $this->conn = $database->getConnection();
    }

    private function validate($data, $required = []) {
        foreach ($required as $field) {
            if (!isset($data[$field]) || trim($data[$field]) === '') {
                return ['status' => 'error', 'message' => "Missing required field: $field"];
            }
        }
        return null;
    }

    // ==================== CREATE ====================
    public function create($data, $userId) {
        $required = ['title', 'taxpayer_name', 'taxpayer_phone', 'appointment_date', 'appointment_time', 'type'];
        $error = $this->validate($data, $required);
        if ($error) return json_encode($error);

        $query = "INSERT INTO appointments (
            title, description, type, location, priority,
            taxpayer_name, taxpayer_phone, invoice_id, invoice_amount,
            appointment_date, appointment_time, duration_minutes,
            created_by, status
        ) VALUES (
            :title, :description, :type, :location, :priority,
            :taxpayer_name, :taxpayer_phone, :invoice_id, :invoice_amount,
            :appointment_date, :appointment_time, :duration_minutes,
            :created_by, 'scheduled'
        )";

        $stmt = $this->conn->prepare($query);
        $stmt->bindValue(':title', $data['title']);
        $stmt->bindValue(':description', $data['description'] ?? null);
        $stmt->bindValue(':type', $data['type']);
        $stmt->bindValue(':location', $data['location'] ?? null);
        $stmt->bindValue(':priority', $data['priority'] ?? 'medium');
        $stmt->bindValue(':taxpayer_name', $data['taxpayer_name']);
        $stmt->bindValue(':taxpayer_phone', $data['taxpayer_phone']);
        $stmt->bindValue(':invoice_id', $data['invoice_id'] ?? null);
        $stmt->bindValue(':invoice_amount', $data['invoice_amount'] ?? null);
        $stmt->bindValue(':appointment_date', $data['appointment_date']);
        $stmt->bindValue(':appointment_time', $data['appointment_time']);
        $stmt->bindValue(':duration_minutes', $data['duration_minutes'] ?? 30);
        $stmt->bindValue(':created_by', $userId);

        return $stmt->execute()
            ? json_encode(['status' => 'success', 'message' => 'Appointment created'])
            : json_encode(['status' => 'error', 'message' => 'Failed to create appointment']);
    }

    // ==================== READ (LIST + FILTER) ====================
    public function getList($filters = [], $userId = null) {
        $query = "SELECT 
            a.*
        FROM appointments a
        WHERE a.deleted_at IS NULL";

        $params = [];

        // User filter: only own appointments (for agents)
        if ($userId && !empty($filters['own_only'])) {
            $query .= " AND a.created_by = :user_id";
            $params[':user_id'] = $userId;
        }

        // Search
        if (!empty($filters['search'])) {
            $search = "%" . $filters['search'] . "%";
            $query .= " AND (a.title LIKE :search OR a.taxpayer_name LIKE :search OR a.invoice_id LIKE :search)";
            $params[':search'] = $search;
        }

        // Filters
        if (!empty($filters['type']) && $filters['type'] !== 'all') {
            $query .= " AND a.type = :type";
            $params[':type'] = $filters['type'];
        }
        if (!empty($filters['priority']) && $filters['priority'] !== 'all') {
            $query .= " AND a.priority = :priority";
            $params[':priority'] = $filters['priority'];
        }
        if (!empty($filters['status']) && $filters['status'] !== 'all') {
            $query .= " AND a.status = :status";
            $params[':status'] = $filters['status'];
        }
        // created by
        if (!empty($filters['created_by']) && is_numeric($filters['created_by'])) {
            $query .= " AND a.created_by = :created_by";
            $params[':created_by'] = $filters['created_by'];
        }

        // Tab filters
        $now = date('Y-m-d');
        $today = date('Y-m-d');
        switch ($filters['tab'] ?? '') {
            case 'today':
                $query .= " AND a.appointment_date = :today";
                $params[':today'] = $today;
                break;
            case 'upcoming':
                $query .= " AND a.appointment_date >= :now AND a.status = 'scheduled' OR a.status = 'rescheduled'  ";
                $params[':now'] = $now;
                break;
            case 'completed':
                $query .= " AND a.status = 'completed'";
                break;
        }

        $query .= " ORDER BY a.appointment_date ASC, a.appointment_time ASC";

        $stmt = $this->conn->prepare($query);
        $stmt->execute($params);
        $appointments = $stmt->fetchAll(PDO::FETCH_ASSOC);

        return json_encode([
            'status' => 'success',
            'data' => $appointments,
            'counts' => $this->getCounts($userId)
        ]);
    }

    private function getCounts($userId = null) {
        $query = "SELECT 
            COUNT(*) as `all`,
            SUM(CASE WHEN status = 'scheduled' AND appointment_date >= CURDATE() THEN 1 ELSE 0 END) as upcoming,
            SUM(CASE WHEN appointment_date = CURDATE() THEN 1 ELSE 0 END) as today,
            SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed
        FROM appointments WHERE deleted_at IS NULL";
        if ($userId) $query .= " AND created_by = :user_id";

        $stmt = $this->conn->prepare($query);
        if ($userId) $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    // ==================== UPDATE (EDIT / RESCHEDULE) ====================
    public function update($id, $data, $userId) {
        $allowed = ['title','description','type','location','priority','appointment_date','appointment_time','duration_minutes','taxpayer_name','taxpayer_phone','invoice_id','invoice_amount'];
        $sets = [];
        $params = [':id' => $id];

        foreach ($allowed as $field) {
            if (isset($data[$field])) {
                $sets[] = "$field = :$field";
                $params[":$field"] = $data[$field];
            }
        }

        if (empty($sets)) {
            return json_encode(['status' => 'error', 'message' => 'No fields to update']);
        }

        // Always set rescheduled if date/time changed
        if (isset($data['appointment_date']) || isset($data['appointment_time'])) {
            $sets[] = "status = 'rescheduled'";
        }

        $query = "UPDATE appointments SET " . implode(', ', $sets) . " WHERE id = :id AND created_by = :user_id AND deleted_at IS NULL";
        $params[':user_id'] = $userId;

        $stmt = $this->conn->prepare($query);
        return $stmt->execute($params)
            ? json_encode(['status' => 'success', 'message' => 'Appointment updated'])
            : json_encode(['status' => 'error', 'message' => 'Failed to update']);
    }

    // ==================== MARK COMPLETE ====================
    public function markComplete($id, $userId, $outcome = null, $notes = null) {
        $query = "UPDATE appointments SET status = 'completed', outcome = :outcome, notes = :notes WHERE id = :id AND created_by = :user_id AND deleted_at IS NULL";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':user_id', $userId);
        $stmt->bindParam(':outcome', $outcome);
        $stmt->bindParam(':notes', $notes);
        return $stmt->execute()
            ? json_encode(['status' => 'success', 'message' => 'Marked as completed'])
            : json_encode(['status' => 'error', 'message' => 'Failed to update']);
    }

    // ==================== CANCEL ====================
    public function cancel($id, $userId) {
        $query = "UPDATE appointments SET status = 'cancelled' WHERE id = :id AND created_by = :user_id AND deleted_at IS NULL";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':user_id', $userId);
        return $stmt->execute()
            ? json_encode(['status' => 'success', 'message' => 'Appointment cancelled'])
            : json_encode(['status' => 'error', 'message' => 'Failed to cancel']);
    }

    // ==================== NO SHOW ====================
    public function noShow($id, $userId) {
        $query = "UPDATE appointments SET status = 'no_show' WHERE id = :id AND created_by = :user_id AND deleted_at IS NULL";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':user_id', $userId);
        return $stmt->execute()
            ? json_encode(['status' => 'success', 'message' => 'Marked as no-show'])
            : json_encode(['status' => 'error', 'message' => 'Failed to update']);
    }

    // ==================== SOFT DELETE ====================
    public function delete($id, $userId) {
        $query = "UPDATE appointments SET deleted_at = NOW() WHERE id = :id AND created_by = :user_id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':user_id', $userId);
        return $stmt->execute()
            ? json_encode(['status' => 'success', 'message' => 'Appointment deleted'])
            : json_encode(['status' => 'error', 'message' => 'Failed to delete']);
    }

    // ==================== GET SINGLE ====================
    public function getOne($id, $userId) {
        $query = "SELECT * FROM appointments WHERE id = :id AND created_by = :user_id AND deleted_at IS NULL";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        $apt = $stmt->fetch(PDO::FETCH_ASSOC);
        return $apt
            ? json_encode(['status' => 'success', 'data' => $apt])
            : json_encode(['status' => 'error', 'message' => 'Not found']);
    }

    // ==================== STATISTICS ====================
    public function getStatistics($userId = null) {
        $query = "SELECT 
            SUM(CASE WHEN appointment_date = CURDATE() THEN 1 ELSE 0 END) as today,
            SUM(CASE WHEN status IN ('scheduled', 'rescheduled') AND appointment_date >= CURDATE() THEN 1 ELSE 0 END) as upcoming,
            SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
            SUM(invoice_amount) as total_amount
        FROM appointments WHERE deleted_at IS NULL";
        $params = [];
        if ($userId) {
            $query .= " AND created_by = :user_id";
            $params[':user_id'] = $userId;
        }

        $stmt = $this->conn->prepare($query);
        $stmt->execute($params);
        $stats = $stmt->fetch(PDO::FETCH_ASSOC);

        return json_encode([
            'status' => 'success',
            'data' => $stats
        ]);
    }
}
