<?php

namespace Modules\Reports\Controllers;

use Modules\Reports\Models\DailyReportModel;
use Modules\Reports\Models\ReportTemplateModel;
use Core\Controller;
use Core\Auth;

class DailyReportController extends Controller
{
    private DailyReportModel $reportModel;
    private ReportTemplateModel $templateModel;

    public function __construct()
    {
        parent::__construct();
        $this->reportModel = new DailyReportModel();
        $this->templateModel = new ReportTemplateModel();
    }

    public function index()
    {
        $this->requireAuth();
        $projectId = (int)$this->getGet('project_id', 0) ?: $this->resolveDefaultProjectId();
        $projects = $this->getAccessibleProjects();

        if (!$projectId) {
            $this->render('reports/daily/index', [
                'reports' => [],
                'projectId' => 0,
                'project' => null,
                'projects' => $projects,
                'filters' => [],
                'paginationData' => null,
            ]);
            return;
        }

        $project = $this->dbQueryOne("SELECT * FROM projects WHERE id = ?", [$projectId]);
        if (!$project || !$this->userCanAccessProject($projectId)) {
            $this->setFlash('error', 'Project not found.');
            $this->redirect('/dashboard');
        }

        $filters = [
            'date_from' => $this->getGet('date_from'),
            'date_to' => $this->getGet('date_to'),
            'contractor_id' => $this->getGet('contractor_id'),
            'status' => $this->getGet('status'),
        ];
        $page = max(1, (int)$this->getGet('page', 1));
        $perPage = 20;

        $reports = $this->reportModel->getForProject($projectId, $filters, $page, $perPage);
        $total = $this->reportModel->countForProject($projectId, $filters);

        $this->render('reports/daily/index', [
            'reports' => $reports,
            'projectId' => $projectId,
            'project' => $project,
            'projects' => $projects,
            'filters' => $filters,
            'paginationData' => [
                'current_page' => $page,
                'total_pages' => (int)ceil($total / $perPage),
                'total_items' => $total,
                'url_pattern' => APP_URL . '/reports/daily?project_id=' . $projectId . '&page=',
            ],
        ]);
    }

    public function create()
    {
        $this->requireAuth();
        $projectId = (int)$this->getGet('project_id', 0) ?: $this->resolveDefaultProjectId();
        if (!$projectId) {
            $this->setFlash('error', 'You have no projects to report on.');
            $this->redirect('/reports/daily');
        }

        $user = Auth::user();
        if (!$this->reportModel->canSubmitReport(Auth::id(), $projectId, $user['entity_type'] ?? 'org_user')) {
            $this->setFlash('error', 'You are not assigned to this project.');
            $this->redirect('/reports/daily');
        }

        $templateId = $this->reportModel->getActiveTemplateId($projectId);
        $templateData = $templateId ? $this->templateModel->getWithSections($templateId) : null;

        $this->render('reports/daily/create', [
            'projectId' => $projectId,
            'template' => $templateData['template'] ?? null,
            'sections' => $templateData['sections'] ?? [],
            'workloadItems' => $templateData['workload_items'] ?? [],
        ]);
    }

    public function store()
    {
        $this->requireAuth();
        if (!$this->validateCsrf()) {
            $this->setFlash('error', 'Invalid security token. Please try again.');
            $this->redirect('/reports/daily');
        }

        $projectId = (int)($_POST['project_id'] ?? 0);
        $user = Auth::user();
        $userId = Auth::id();

        if (!$projectId || !$this->reportModel->canSubmitReport($userId, $projectId, $user['entity_type'] ?? 'org_user')) {
            $this->setFlash('error', 'You are not assigned to this project.');
            $this->redirect('/reports/daily');
        }

        $contractorId = null;
        if (($user['entity_type'] ?? '') === 'contractor_user') {
            $contractorId = $this->reportModel->getContractorIdForUser($userId);
        }

        $reportData = [
            'project_id' => $projectId,
            'contractor_id' => $contractorId,
            'submitted_by' => $userId,
            'report_date' => $_POST['date'] ?? date('Y-m-d'),
            'weather' => $_POST['weather'] ?? null,
            'manpower_count' => (int)($_POST['manpower'] ?? 0),
            'site_notes' => $_POST['site_notes'] ?? '',
            'status' => isset($_POST['submit']) ? 'submitted' : 'draft',
        ];

        $sectionEntries = $_POST['sections'] ?? [];
        $workloadEntries = $_POST['workload'] ?? [];
        $attachments = $this->processReportUploads($_FILES['files'] ?? []);

        $reportId = $this->reportModel->createReport($reportData, $sectionEntries, $workloadEntries, $attachments);

        if ($reportData['status'] === 'submitted') {
            $this->reportModel->notifyPM($projectId, $reportId);
        }

        logAudit('daily_report_' . $reportData['status'], 'reports', 'project_report', $reportId);
        $this->setFlash('success', 'Report saved successfully.');
        $this->redirect('/reports/daily/' . $reportId);
    }

    public function show($reportId)
    {
        $this->requireAuth();
        $reportData = $this->reportModel->getWithDetails((int)$reportId);
        if (!$reportData || !$this->userCanAccessProject((int)$reportData['report']['project_id'])) {
            $this->setFlash('error', 'Report not found.');
            $this->redirect('/reports/daily');
        }

        $this->render('reports/daily/show', [
            'report' => $reportData['report'],
            'sectionEntries' => $reportData['section_entries'],
            'workloadEntries' => $reportData['workload_entries'],
            'attachments' => $reportData['attachments'],
        ]);
    }

    public function review($reportId)
    {
        $this->requireAuth();
        if (!$this->validateCsrf()) {
            $this->setFlash('error', 'Invalid security token. Please try again.');
            $this->redirect('/reports/daily/' . $reportId);
        }

        $reportData = $this->reportModel->getWithDetails((int)$reportId);
        if (!$reportData || !$this->userCanAccessProject((int)$reportData['report']['project_id'])) {
            $this->setFlash('error', 'Report not found.');
            $this->redirect('/reports/daily');
        }

        $status = ($_POST['action'] ?? '') === 'approve' ? 'approved' : 'reviewed';
        $notes = $_POST['pm_notes'] ?? '';

        $this->reportModel->updateReviewStatus((int)$reportId, $status, $notes, Auth::id());
        logAudit('daily_report_reviewed', 'reports', 'project_report', (int)$reportId, null, ['status' => $status]);
        $this->setFlash('success', 'Report review saved.');
        $this->redirect('/reports/daily/' . $reportId);
    }

    public function progressDashboard()
    {
        $this->requireAuth();
        $projectId = (int)$this->getGet('project_id', 0) ?: $this->resolveDefaultProjectId();
        if (!$projectId || !$this->userCanAccessProject($projectId)) {
            $this->setFlash('error', 'Project not found.');
            $this->redirect('/reports/daily');
        }

        $project = $this->dbQueryOne("SELECT * FROM projects WHERE id = ?", [$projectId]);
        $summary = $this->reportModel->getProgressSummary($projectId);
        $chartData = $this->reportModel->getDailyProgressChart($projectId);
        $recentPhotos = $this->reportModel->getRecentPhotos($projectId);
        $totalReports = $this->reportModel->countForProject($projectId, []);

        $this->render('reports/daily/progress_dashboard', [
            'projectId' => $projectId,
            'project' => $project,
            'summary' => $summary,
            'chartData' => $chartData,
            'recentPhotos' => $recentPhotos,
            'totalReports' => $totalReports,
        ]);
    }

    private function processReportUploads(array $filesInput): array
    {
        $attachments = [];
        foreach ($filesInput['name'] ?? [] as $sectionId => $names) {
            foreach ($names as $i => $name) {
                if (empty($name) || $filesInput['error'][$sectionId][$i] !== UPLOAD_ERR_OK) {
                    continue;
                }
                $fileInput = [
                    'name' => $filesInput['name'][$sectionId][$i],
                    'type' => $filesInput['type'][$sectionId][$i],
                    'tmp_name' => $filesInput['tmp_name'][$sectionId][$i],
                    'error' => $filesInput['error'][$sectionId][$i],
                    'size' => $filesInput['size'][$sectionId][$i],
                ];
                $upload = $this->uploadFile($fileInput, 'reports');
                if ($upload) {
                    $attachments[] = [
                        'section_id' => (int)$sectionId,
                        'name' => $upload['name'],
                        'path' => $upload['path'],
                        'size' => $upload['size'],
                        'mime' => $fileInput['type'],
                    ];
                }
            }
        }
        return $attachments;
    }

    private function resolveDefaultProjectId(): int
    {
        $user = Auth::user();
        if (($user['entity_type'] ?? '') === 'contractor_user') {
            $contractorId = $this->reportModel->getContractorIdForUser(Auth::id());
            if (!$contractorId) {
                return 0;
            }
            $row = $this->dbQueryOne(
                "SELECT project_id FROM project_contractors WHERE contractor_id = ? AND status = 'accepted' ORDER BY assigned_at DESC LIMIT 1",
                [$contractorId]
            );
            return $row ? (int)$row['project_id'] : 0;
        }

        $row = $this->dbQueryOne(
            "SELECT id FROM projects WHERE org_id = ? AND status = 'active' ORDER BY created_at DESC LIMIT 1",
            [Auth::orgId()]
        );
        return $row ? (int)$row['id'] : 0;
    }

    private function getAccessibleProjects(): array
    {
        $user = Auth::user();
        if (($user['entity_type'] ?? '') === 'contractor_user') {
            $contractorId = $this->reportModel->getContractorIdForUser(Auth::id());
            if (!$contractorId) {
                return [];
            }
            return $this->dbQuery(
                "SELECT p.id, p.name FROM project_contractors pc
                 INNER JOIN projects p ON pc.project_id = p.id
                 WHERE pc.contractor_id = ? AND pc.status = 'accepted' ORDER BY p.name",
                [$contractorId]
            );
        }

        return $this->dbQuery("SELECT id, name FROM projects WHERE org_id = ? ORDER BY name", [Auth::orgId()]);
    }

    private function userCanAccessProject(int $projectId): bool
    {
        $user = Auth::user();
        if (($user['entity_type'] ?? '') === 'contractor_user') {
            return $this->reportModel->canSubmitReport(Auth::id(), $projectId, 'contractor_user');
        }
        $row = $this->dbQueryOne("SELECT id FROM projects WHERE id = ? AND org_id = ?", [$projectId, Auth::orgId()]);
        return (bool)$row;
    }
}
