<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\HTTP\ResponseInterface;

class ReportsController extends ResourceController
{
    protected $modelName = 'App\Models\ReportModel';
    protected $invoiceModel;
    protected $reportDetailModel;  
    protected $invoiceTestModel;
    protected $testItemModel;

    /**
     * ReportsController constructor.
     */
    public function __construct()
    {
        $this->invoiceModel = model('App\Models\InvoiceModel');
        $this->reportDetailModel = model('App\Models\ReportDetailModel');
        $this->invoiceTestModel = model('App\Models\InvoiceTestModel');
        $this->testItemModel = model('App\Models\TestItemModel');
    }

    /**
     * Return the count of resources in the collection.
     *
     * @return ResponseInterface
     */
    public function count() 
    {
        $total = $this->model->countAll();
        return $this->respond(['total' => $total]);
    }

    /**
     * Return an array of resource objects, themselves in array format.
     *
     * @return ResponseInterface
     */
    public function index()
    {
        $this->respond('success');
        $perPage = $this->request->getVar('limit') ?? 10;
        $offset  = $this->request->getVar('offset') ?? 1;
        $search = $this->request->getVar('search') ?? '';
        $search = trim($search);

        $reports = [];
        if( $search !== '') {
            $reports = $this->model
                ->groupStart()
                    ->like('patients.name', $search)
                    ->orLike('patients.phone', $search)
                    ->orLike('invoices.lab_number', $search)
                    ->orLike('invoice_tests.status', $search)
                ->groupEnd()
                ->select('reports.*, patients.id as patient_id, patients.name as patient_name, patients.age as patient_age, patients.sex as patient_sex, invoices.lab_number as lab_number, tests.name as test_name, invoice_tests.status as status')
                ->join('invoice_tests', 'invoice_tests.id = reports.invoice_test_id')
                ->join('invoices', 'invoices.id = invoice_tests.invoice_id')
                ->join('patients', 'patients.id = invoices.patient_id')
                ->join('tests', 'tests.id = invoice_tests.test_id')
                ->orderBy('reports.id', 'DESC')
                ->paginate($perPage, 'default', $offset);
        } else {
            $reports = $this->model
                ->select('reports.*, patients.id as patient_id, patients.name as patient_name, patients.age as patient_age, patients.sex as patient_sex, invoices.lab_number as lab_number, tests.name as test_name, invoice_tests.status as status')
                ->join('invoice_tests', 'invoice_tests.id = reports.invoice_test_id')
                ->join('invoices', 'invoices.id = invoice_tests.invoice_id')
                ->join('patients', 'patients.id = invoices.patient_id')
                ->join('tests', 'tests.id = invoice_tests.test_id')
                ->orderBy('reports.id', 'DESC')
                ->paginate($perPage, 'default', $offset);
        }

        $response = [
            'data' => $reports,
            'pager' => $this->model->pager->getDetails()
        ];

        return $this->respond($response);
    }

    /**
     * Return the properties of a resource object.
     *
     * @param int|string|null $id
     *
     * @return ResponseInterface
     */
    public function show($id = null)
    {
        if ($id === null) {
            return $this->failNotFound('Report ID is required');
        }

        $report = $this->model
                    ->select('reports.*, invoices.lab_number as lab_number, invoices.referred_by as referred_by, tests.id as test_id, tests.name as test_name, invoice_tests.status as status, patients.id as patient_id, patients.name as patient_name, patients.age as patient_age, patients.sex as patient_sex, patients.phone as patient_phone')
                    ->join('invoice_tests', 'invoice_tests.id = reports.invoice_test_id')
                    ->join('invoices', 'invoices.id = invoice_tests.invoice_id')
                    ->join('patients', 'patients.id = invoices.patient_id')
                    ->join('tests', 'tests.id = invoice_tests.test_id')
                    ->find($id);
        if (!$report) {
            return $this->failNotFound('Report not found');
        }

        $testItems  = $this->testItemModel
            ->select('test_items.*')
            ->where('test_items.test_id', $report['test_id'])
            ->findAll();

        $reportDetails = $this->reportDetailModel
            ->where('report_id', $id)
            ->findAll();

        $detailsByTestItemId = [];
        foreach ($reportDetails as $detail) {
            $detailsByTestItemId[$detail['test_item_id']] = $detail;
        }

        foreach ($testItems as &$item) {
            $item['test_item_id'] = $item['id'];
            $detail = $detailsByTestItemId[$item['test_item_id']] ?? null;

            $item['id'] = $detail['id'] ?? null;
            $item['result'] = $detailsByTestItemId[$item['test_item_id']]['result'] ?? null;
            $item['remarks'] = $detailsByTestItemId[$item['test_item_id']]['remarks'] ?? null;
        }
        unset($item);

        $report['report_details'] = $testItems;
        return $this->respond($report);
    }

    /**
     * Return a new resource object, with default properties.
     *
     * @return ResponseInterface
     */
    public function new()
    {
        $report = $this->model->getDefaultValues();
        $report['report_details'] = $this->reportDetailModel->getDefaultValues();;
    }

    /**
     * Create a new resource object, from "posted" parameters.
     *
     * @return ResponseInterface
     */
    public function create()
    {
        $data = (array)$this->request->getVar();
        if (!$data) {
            return $this->fail('No data provided');
        }

        $details = (array)$data['details'] ?? [];
        if (empty($details)) {
            return $this->fail('Report details are required');
        }

        $reportId = $this->model->insert($data);
        if (!$reportId) {
            return $this->failServerError('Failed to create report');
        }

        foreach ($details as &$detail) {
            $detail = (array)$detail;
            $detail['report_id'] = $reportId;
        }

        error_log(print_r($details, true)); // Debugging line to check details structure

        if (!$this->reportDetailModel->insertBatch($details)) {
            return $this->failServerError('Failed to create report details');
        }

        $this->invoiceTestModel->update($data['invoice_test_id'], ['status' => 'Completed']);


        return $this->respondCreated(['message' => 'Report created successfully', 'id' => $reportId]);
    }

    /**
     * Return the editable properties of a resource object.
     *
     * @param int|string|null $id
     *
     * @return ResponseInterface
     */
    public function edit($id = null)
    {
        if ($id === null) {
            return $this->failNotFound('Report ID is required');
        }

        $report = $this->model
            ->select('reports.*, invoices.lab_number as lab_number, tests.name as test_name, invoice_tests.status as status, patients.id as patient_id, patients.name as patient_name, patients.age as patient_age, patients.sex as patient_sex, patients.phone as patient_phone')
            ->join('invoice_tests', 'invoice_tests.id = reports.invoice_test_id')
            ->join('invoices', 'invoices.id = invoice_tests.invoice_id')
            ->join('patients', 'patients.id = invoices.patient_id')
            ->join('tests', 'tests.id = invoice_tests.test_id')
            ->find($id);
        if (!$report) {
            return $this->failNotFound('Report not found');
        }

        $report['report_details'] = $this->reportDetailModel->where('report_id', $id)->findAll();
        return $this->respond($report);
    }

    /**
     * Add or update a model resource, from "posted" properties.
     *
     * @param int|string|null $id
     *
     * @return ResponseInterface
     */
    public function update($id = null)
    {
        if( $id === null) {
            return $this->failNotFound('Report ID is required');
        }
        
        $details = (array)$this->request->getVar('details') ?? [];
        if (empty($details)) {
            return $this->fail('Report details are required');
        }

        $report = $this->model->find($id);
        if (!$report) {
            return $this->failNotFound('Report not found');
        }
        
        foreach( $details as &$detail ) {
            $detail = (array)$detail;
        }

        $this->reportDetailModel
            ->updateBatch($details, 'id');

        return $this->respondUpdated(['message' => 'Report updated successfully', 'id' => $id]);
    }

    /**
     * Delete the designated resource object from the model.
     *
     * @param int|string|null $id
     *
     * @return ResponseInterface
     */
    public function delete($id = null)
    {
        if ($id === null) {
            return $this->failNotFound('Report ID is required');
        }

        $report = $this->model->find($id);
        if (!$report) {
            return $this->failNotFound('Report not found');
        }

        if (!$this->model->delete($id)) {
            return $this->failServerError('Failed to delete report');
        } 
        
        return $this->respondDeleted(['message' => 'Report deleted successfully']);
    }

    public function getReportsByPatientId($patientId = null)
    {
        if ($patientId === null) {
            return $this->failNotFound('Patient ID is required');
        }

        $reports = $this->model
        ->select('reports.*, patients.id as patient_id, patients.name as patient_name, patients.age as patient_age, patients.sex as patient_sex, invoices.lab_number as lab_number, tests.name as test_name, invoice_tests.status as status')
            ->join('invoice_tests', 'invoice_tests.id = reports.invoice_test_id')
            ->join('invoices', 'invoices.id = invoice_tests.invoice_id')
            ->join('patients', 'patients.id = invoices.patient_id')
            ->join('tests', 'tests.id = invoice_tests.test_id')
            ->orderBy('reports.id', 'DESC')
            ->where('patients.id', $patientId)
            ->findAll();

        return $this->respond($reports);
    }
}
