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

class CallAnalyticsController {
    private $conn;

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

    private function getPeriodFilter($period) {
        switch ($period) {
            case 'day':
                return "DATE(c.created_at) = CURDATE()";
            case 'month':
                return "c.created_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)";
            case 'quarter':
                return "c.created_at >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)";
            case 'week':
            default:
                return "c.created_at >= DATE_SUB(CURDATE(), INTERVAL 1 WEEK)";
        }
    }

    public function getOverallMetrics($params, $user_id, $user_role) {
        try {
            $period = $params['period'] ?? 'week';
            if (!in_array($period, ['day', 'week', 'month', 'quarter'])) {
                return json_encode(['status' => 'error', 'message' => 'Invalid period']);
            }

            // $where = [$this->getPeriodFilter($period)];
            $bindings = [];
            if ($user_role === 3) { // IPO
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $user_id;
            } elseif (isset($params['ipo_id']) && $user_role <= 2) { // Admin/Supervisor
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $params['ipo_id'];
            }

            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

            $query = "
                SELECT 
                    COUNT(c.id) AS totalCalls,
                    SUM(CASE WHEN c.status IN ('connected', 'completed', 'failed') THEN 1 ELSE 0 END) AS connectedCalls,
                    SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN 1 ELSE 0 END) AS successfulOutcomes,
                    COALESCE(SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN i.amount ELSE 0 END), 0) AS amountRecovered,
                    COALESCE(AVG(CASE WHEN c.duration IS NOT NULL THEN c.duration / 60 END), 0) AS avgCallDuration
                FROM calls c
                JOIN follow_ups f ON c.follow_up_id = f.id
                LEFT JOIN invoices i ON f.invoice_id = i.id
                LEFT JOIN users u ON f.ipo_id = u.id
                $whereSql
            ";
            $stmt = $this->conn->prepare($query);
            foreach ($bindings as $key => $val) {
                $stmt->bindValue($key, $val);
            }
            $stmt->execute();
            $data = $stmt->fetch(PDO::FETCH_ASSOC);

            $totalCalls = (int)($data['totalCalls'] ?? 0);
            $data['connectionRate'] = $totalCalls ? ($data['connectedCalls'] / $totalCalls) * 100 : 0;
            $data['conversionRate'] = $data['connectedCalls'] ? ($data['successfulOutcomes'] / $data['connectedCalls']) * 100 : 0;
            $data['totalCalls'] = $totalCalls;
            $data['connectedCalls'] = (int)($data['connectedCalls'] ?? 0);
            $data['successfulOutcomes'] = (int)($data['successfulOutcomes'] ?? 0);
            $data['amountRecovered'] = (float)($data['amountRecovered'] ?? 0);
            $data['avgCallDuration'] = (float)($data['avgCallDuration'] ?? 0);

            return json_encode([
                'status' => 'success',
                'data' => $data
            ]);
        } catch (Exception $e) {
            return json_encode(['status' => 'error', 'message' => 'Exception: ' . $e->getMessage()]);
        }
    }

    public function getIpoPerformance($params, $user_id, $user_role) {
        try {
            $period = $params['period'] ?? 'week';
            if (!in_array($period, ['day', 'week', 'month', 'quarter'])) {
                return json_encode(['status' => 'error', 'message' => 'Invalid period']);
            }

            $where = [$this->getPeriodFilter($period)];
            $bindings = [];
            if ($user_role === 3) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $user_id;
            } elseif (isset($params['ipo_id']) && $user_role <= 2) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $params['ipo_id'];
            }

            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

            // Static targets for now (80 calls, 2M NGN per period)
            $callVolumeTarget = 80;
            $amountTarget = 2000000;

            $query = "
                SELECT 
                    CONCAT(u.first_name, ' ', u.last_name) AS ipoName,
                    u.id AS ipoId,
                    COUNT(c.id) AS totalCalls,
                    SUM(CASE WHEN c.status IN ('connected', 'failed') THEN 1 ELSE 0 END) AS connectedCalls,
                    SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN 1 ELSE 0 END) AS successfulOutcomes,
                    COALESCE(SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN i.amount ELSE 0 END), 0) AS amountRecovered,
                    COALESCE(AVG(CASE WHEN c.duration IS NOT NULL THEN c.duration / 60 END), 0) AS avgCallDuration
                FROM calls c
                JOIN follow_ups f ON c.follow_up_id = f.id
                LEFT JOIN invoices i ON f.invoice_id = i.id
                LEFT JOIN users u ON f.ipo_id = u.id
                $whereSql
                GROUP BY u.id, u.first_name, u.last_name
            ";
            $stmt = $this->conn->prepare($query);
            foreach ($bindings as $key => $val) {
                $stmt->bindValue($key, $val);
            }
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $data = array_map(function ($row) use ($callVolumeTarget, $amountTarget) {
                $totalCalls = (int)($row['totalCalls'] ?? 0);
                $connectedCalls = (int)($row['connectedCalls'] ?? 0);
                return [
                    'ipoName' => $row['ipoName'],
                    'ipoId' => (int)$row['ipoId'],
                    'totalCalls' => $totalCalls,
                    'connectedCalls' => $connectedCalls,
                    'successfulOutcomes' => (int)($row['successfulOutcomes'] ?? 0),
                    'amountRecovered' => (float)($row['amountRecovered'] ?? 0),
                    'avgCallDuration' => (float)($row['avgCallDuration'] ?? 0),
                    'conversionRate' => $connectedCalls ? ($row['successfulOutcomes'] / $connectedCalls) * 100 : 0,
                    'volumeTargetAchievement' => $callVolumeTarget ? ($totalCalls / $callVolumeTarget) * 100 : 0,
                    'amountTargetAchievement' => $amountTarget ? ($row['amountRecovered'] / $amountTarget) * 100 : 0
                ];
            }, $rows);

            return json_encode([
                'status' => 'success',
                'data' => $data
            ]);
        } catch (Exception $e) {
            return json_encode(['status' => 'error', 'message' => 'Exception: ' . $e->getMessage()]);
        }
    }

    public function getCallOutcomes($params, $user_id, $user_role) {
        try {
            $period = $params['period'] ?? 'week';
            if (!in_array($period, ['day', 'week', 'month', 'quarter'])) {
                return json_encode(['status' => 'error', 'message' => 'Invalid period']);
            }

            $where = [$this->getPeriodFilter($period)];
            $bindings = [];
            if ($user_role === 3) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $user_id;
            } elseif (isset($params['ipo_id']) && $user_role <= 2) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $params['ipo_id'];
            }

            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

            $query = "
                SELECT 
                    CASE 
                        WHEN c.status = 'connected' AND f.status = 'closed' THEN 'Payment Successful'
                        WHEN f.status = 'rescheduled' THEN 'Rescheduled'
                        WHEN c.status = 'connected' THEN 'Payment Plan'
                        WHEN f.status = 'escalated' THEN 'Escalated'
                        WHEN c.status = 'no_answer' THEN 'Not Reachable'
                        WHEN c.status = 'failed' THEN 'Closed/Invalid'
                        ELSE 'Other'
                    END AS outcome,
                    COUNT(*) AS count
                FROM calls c
                JOIN follow_ups f ON c.follow_up_id = f.id
                LEFT JOIN invoices i ON f.invoice_id = i.id
                LEFT JOIN users u ON f.ipo_id = u.id
                $whereSql
                GROUP BY outcome
            ";
            $stmt = $this->conn->prepare($query);
            foreach ($bindings as $key => $val) {
                $stmt->bindValue($key, $val);
            }
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $total = array_sum(array_column($rows, 'count'));
            $data = array_map(function ($row) use ($total) {
                return [
                    'outcome' => $row['outcome'],
                    'count' => (int)$row['count'],
                    'percentage' => $total ? ($row['count'] / $total) * 100 : 0
                ];
            }, $rows);

            return json_encode([
                'status' => 'success',
                'data' => $data
            ]);
        } catch (Exception $e) {
            return json_encode(['status' => 'error', 'message' => 'Exception: ' . $e->getMessage()]);
        }
    }

    public function getDailyTrends($params, $user_id, $user_role) {
        try {
            $period = $params['period'] ?? 'week';
            if (!in_array($period, ['day', 'week', 'month', 'quarter'])) {
                return json_encode(['status' => 'error', 'message' => 'Invalid period']);
            }

            $where = [$this->getPeriodFilter($period)];
            $bindings = [];
            if ($user_role === 3) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $user_id;
            } elseif (isset($params['ipo_id']) && $user_role <= 2) {
                $where[] = "f.ipo_id = :ipo_id";
                $bindings[':ipo_id'] = $params['ipo_id'];
            }

            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

            $query = "
                SELECT 
                    DATE_FORMAT(c.created_at, '%Y-%m-%d') AS date,
                    COUNT(c.id) AS totalCalls,
                    SUM(CASE WHEN c.status IN ('connected', 'failed') THEN 1 ELSE 0 END) AS connectedCalls,
                    SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN 1 ELSE 0 END) AS successfulCalls,
                    COALESCE(SUM(CASE WHEN c.status = 'connected' AND f.status = 'closed' THEN i.amount ELSE 0 END), 0) AS amountRecovered
                FROM calls c
                JOIN follow_ups f ON c.follow_up_id = f.id
                LEFT JOIN invoices i ON f.invoice_id = i.id
                LEFT JOIN users u ON f.ipo_id = u.id
                $whereSql
                GROUP BY DATE(c.created_at)
                ORDER BY date ASC
            ";
            $stmt = $this->conn->prepare($query);
            foreach ($bindings as $key => $val) {
                $stmt->bindValue($key, $val);
            }
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $data = array_map(function ($row) {
                return [
                    'date' => $row['date'],
                    'totalCalls' => (int)$row['totalCalls'],
                    'connectedCalls' => (int)$row['connectedCalls'],
                    'successfulCalls' => (int)$row['successfulCalls'],
                    'amountRecovered' => (float)$row['amountRecovered']
                ];
            }, $rows);

            return json_encode([
                'status' => 'success',
                'data' => $data
            ]);
        } catch (Exception $e) {
            return json_encode(['status' => 'error', 'message' => 'Exception: ' . $e->getMessage()]);
        }
    }
}