<?php

namespace Modules\Dashboard\Services\PKJ;

use Modules\Dashboard\Services\DashboardService;
use Modules\Dashboard\Repositories\Contracts\PKJDashboardRepositoryInterface;
use Modules\PKJAssetEntitlement\Entities\PKJAssetEntitlement;
use Modules\PKJAssetHolding\Entities\PKJAssetHolding;
use Modules\PKJRepair\Entities\PKJRepair;
use Modules\PKJReport\Entities\PKJReport;
use App\Services\VisibilityService;
use Carbon\Carbon;

class PKJDashboardService extends DashboardService
{
    protected PKJDashboardRepositoryInterface $pkjDashboardRepository;

    public function __construct(
        VisibilityService $visibilityService,
        PKJDashboardRepositoryInterface $pkjDashboardRepository
    ) {
        parent::__construct($visibilityService);
        $this->pkjDashboardRepository = $pkjDashboardRepository;
    }
    /**
     * Get total PKJ assets
     */
    public function getTotalAssets(array $filters = [], $user = null): int
    {
        return $this->pkjDashboardRepository->getTotalHoldings($filters, $user);
    }

    /**
     * Get operational PKJ assets (BP status)
     */
    public function getOperationalAssets(array $filters = [], $user = null): int
    {
        $holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('BP', $filters, $user);
        return $holdings['pagination']['total'];
    }

    /**
     * Get under repair PKJ assets (TBDG status)
     */
    public function getUnderRepairAssets(array $filters = [], $user = null): int
    {
        $holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('TBDG', $filters, $user);
        return $holdings['pagination']['total'];
    }

    /**
     * Get maintenance due PKJ assets (BDG status)
     */
    public function getMaintenanceDueAssets(array $filters = [], $user = null): int
    {
        $holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('BDG', $filters, $user);
        return $holdings['pagination']['total'];
    }

    /**
     * Get active PKJ repairs
     */
    public function getActiveRepairs(array $filters = []): int
    {
        $dateRange = $this->getDateRange($filters);
        
        return PKJRepair::query()
            ->whereBetween('created_at', [$dateRange['from'], $dateRange['to']])
            ->where('status', 'active')
            ->count();
    }

    /**
     * Get pending PKJ reports
     */
    public function getPendingReports(array $filters = []): int
    {
        $dateRange = $this->getDateRange($filters);
        
        return PKJReport::query()
            ->whereBetween('created_at', [$dateRange['from'], $dateRange['to']])
            ->where('status', 'pending')
            ->count();
    }

    /**
     * Get PKJ entitlement vs holdings pie chart
     */
    public function getEntitlementVsHoldingsPieChart(array $filters = [], $user = null): array
    {
        $totalEntitlement = $this->pkjDashboardRepository->getTotalEntitlement($filters, $user);
        $totalHoldings = $this->pkjDashboardRepository->getTotalHoldings($filters, $user);

        $data = [
            [
                'name' => 'Perjawatan',
                'value' => $totalEntitlement,
                'percentage' => ($totalEntitlement + $totalHoldings) > 0 ? round(($totalEntitlement / ($totalEntitlement + $totalHoldings)) * 100, 2) : 0
            ],
            [
                'name' => 'Pegangan',
                'value' => $totalHoldings,
                'percentage' => ($totalEntitlement + $totalHoldings) > 0 ? round(($totalHoldings / ($totalEntitlement + $totalHoldings)) * 100, 2) : 0
            ]
        ];

        return $this->formatPieChartData(
            'Perjawatan vs Pegangan PKJ',
            $data,
            '', // No drill-down
            []
        );
    }

    /**
     * Get PKJ holdings status breakdown pie chart
     */
    public function getHoldingsStatusBreakdownPieChart(array $filters = [], $user = null): array
    {
        $statusCounts = $this->pkjDashboardRepository->getHoldingsByStatus($filters, $user);
        
        // Map status codes to readable names
        $statusNames = [
            'BP' => 'Baik dalam Perhatian',
            'BDG' => 'Boleh Digunakan',
            'TBDG' => 'Tidak Boleh Digunakan',
            'BT' => 'Boleh Tembak',
            'BG' => 'Baik Guna'
        ];

        $data = [];
        foreach ($statusCounts as $status) {
            $statusName = $statusNames[$status['status']] ?? $status['status'];
            $data[] = [
                'name' => $statusName,
                'value' => $status['count'],
                'percentage' => 0 // Will be calculated after total
            ];
        }

        // Calculate percentages
        $total = array_sum(array_column($data, 'value'));
        foreach ($data as &$item) {
            $item['percentage'] = $total > 0 ? round(($item['value'] / $total) * 100, 2) : 0;
        }

        return $this->formatPieChartData(
            'PKJ Status Pegangan',
            $data,
            '', // No drill-down
            []
        );
    }

    /**
     * Get PKJ monthly trends chart
     */
    public function getMonthlyTrendsChart(array $filters = [], $user = null): array
    {
        $monthlyData = $this->pkjDashboardRepository->getMonthlyTrends($filters, $user);
        
        $categories = [];
        $data = [];
        
        foreach ($monthlyData as $trend) {
            $categories[] = Carbon::createFromFormat('Y-m', $trend['month'])->format('M Y');
            $data[] = $trend['total_reports'];
        }

        return $this->formatBarChartData(
            'Trend Bulanan PKJ 2025',
            [
                ['name' => 'Laporan', 'data' => $data]
            ],
            $categories
        );
    }

    /**
     * Get PKJ holdings by category bar chart
     */
    public function getHoldingsByCategoryBarChart(array $filters = [], $user = null): array
    {
        $categoryData = $this->pkjDashboardRepository->getHoldingsByCategory($filters, $user);
        
        $categories = [];
        $categoryIds = [];
        $data = [];
        
        foreach ($categoryData as $category) {
            $categories[] = $category['category_name'];
            $categoryIds[] = (int) $category['category_id'];
            $data[] = (int) $category['total_holding'];
        }

        $chartData = $this->formatBarChartData(
            'Pegangan PKJ Mengikut Kategori',
            [
                ['name' => 'Jumlah Pegangan', 'data' => $data]
            ],
            $categories
        );

        // Add category IDs to the chart data for drill-down functionality
        $chartData['category_ids'] = $categoryIds;

        return $chartData;
    }

    /**
     * Get PKJ category metrics bar chart (drill-down)
     */
    public function getCategoryMetricsBarChart(int $categoryId, array $filters = [], $user = null): array
    {
        $metrics = $this->pkjDashboardRepository->getCategoryMetrics($categoryId, $filters, $user);
        
        $categories = ['KEUPAYAAN (%)', 'KESIAGAAN (%)', 'SERVISIBILITI (%)'];
        $data = [
            $metrics['keupayaan'],
            $metrics['kesiagaan'],
            $metrics['servisibiliti']
        ];

        $chartData = $this->formatBarChartData(
            'Metrik Kategori PKJ',
            [
                ['name' => 'Metrics', 'data' => $data]
            ],
            $categories
        );

        // Add category information to the response
        $chartData['category_id'] = $metrics['category_id'];
        $chartData['category_name'] = $metrics['category_name'];

        return $chartData;
    }

    /**
     * Get PKJ category status breakdown pie chart (drill-down)
     */
    public function getCategoryStatusBreakdownPieChart(int $categoryId, array $filters = [], $user = null): array
    {
        $breakdown = $this->pkjDashboardRepository->getCategoryStatusBreakdown($categoryId, $filters, $user);
        
        // Map status codes to readable names
        $statusNames = [
            'BP' => 'Baik dalam Perhatian',
            'BDG' => 'Boleh Digunakan',
            'TBDG' => 'Tidak Boleh Digunakan',
            'BT' => 'Boleh Tembak',
            'TBT' => 'Tidak Boleh Tembak',
            'BG' => 'Baik Guna',
            'TBG' => 'Tidak Baik Guna',
        ];

        $data = [];
        foreach ($breakdown['status_breakdown'] as $status) {
            $statusCode = $status['status'];
            
            // In the breakdown, status_code is null when the asset has no status (DB column is NULL).
            if ($statusCode === null || $statusCode === '') {
                $statusName = 'Status Tidak Diketahui';
            } else {
                $statusName = $statusNames[$statusCode] ?? $statusCode;
            }
            
            $data[] = [
                'name' => $statusName,
                'value' => $status['count'],
                'percentage' => 0, // Will be calculated after total
                'status_code' => $statusCode // null when DB status column is NULL (Belum Diberi Status)
            ];
        }

        // Calculate percentages
        $total = array_sum(array_column($data, 'value'));
        foreach ($data as &$item) {
            $item['percentage'] = $total > 0 ? round(($item['value'] / $total) * 100, 2) : 0;
        }

        $chartData = $this->formatPieChartData(
            'PKJ Status Pegangan Mengikut Kategori',
            $data,
            '/v1/dashboard/pkj/category/' . $categoryId . '/status-details',
            ['status']
        );

        // Add category information to the response
        $chartData['category_id'] = $breakdown['category_id'];
        $chartData['category_name'] = $breakdown['category_name'];

        return $chartData;
    }

    /**
     * Get unit ID column name for PKJ
     */
    protected function getUnitIdColumn(): string
    {
        return 'pkj_asset_holdings.unit_id';
    }

    /**
     * Get asset model class for PKJ
     */
    protected function getAssetModelClass(): string
    {
        return PKJAssetHolding::class;
    }

    /**
     * Get repair model class for PKJ
     */
    protected function getRepairModelClass(): string
    {
        return PKJRepair::class;
    }
}
