<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use App\Controllers\BaseController;

class RequestsController extends BaseController
{
  use ResponseTrait;

  private const MAX_PAGE_SIZE = 100;

  public function index()
  {
    $db = \Config\Database::connect();
    $today = date('Y-m-d');
    $date1 = (string) ($this->request->getGet('date1') ?: $today);
    $date2 = (string) ($this->request->getGet('date2') ?: $today);
    $userroleid = (int) session()->get('userroleid');

    $page = max(1, (int) ($this->request->getGet('page') ?? 1));
    $pageSize = (int) ($this->request->getGet('pageSize') ?? 50);
    $pageSize = max(1, min(self::MAX_PAGE_SIZE, $pageSize));
    $offset = ($page - 1) * $pageSize;

    $sortCol = (string) ($this->request->getGet('sortCol') ?? 'REQDATE');
    $sortDirRaw = strtoupper((string) ($this->request->getGet('sortDir') ?? 'DESC'));
    $sortDir = $sortDirRaw === 'ASC' ? 'ASC' : 'DESC';
    $sortSql = $this->resolveSortColumn($sortCol);

    $filterKey = (string) ($this->request->getGet('filterKey') ?? 'Total');
    $search = trim((string) ($this->request->getGet('search') ?? ''));

    [$baseWhereSql, $baseParams] = $this->buildBaseWhereClause($date1, $date2, $userroleid);
    [$whereSql, $whereParams] = $this->buildDashboardWhereClause($baseWhereSql, $baseParams, $filterKey, $search);

    $rowsSql = "SELECT
        d.REQDATE,
        d.[Name],
        d.SP_ACCESSNUMBER,
        d.HOSTORDERNUMBER,
        d.REFF,
        d.DOC,
        d.TESTS,
        d.ODR_CRESULT_TO,
        d.STATS,
        d.COLLECTIONDATE,
        d.[Name] AS PATNAME,
        CAST(NULL AS VARCHAR(32)) AS PATNUMBER,
        r.VAL1USER,
        r.VAL2USER,
        r.ISPENDING,
        r.REPORT_LANG,
        r.ISPDF
      FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
      LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER
      WHERE {$whereSql}
      ORDER BY {$sortSql} {$sortDir}
      OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";

    $rowsParams = [...$whereParams, $offset, $pageSize];
    $rows = $db->query($rowsSql, $rowsParams)->getResultArray();

    $countSql = "SELECT COUNT(1) AS total
      FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
      LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER
      WHERE {$whereSql}";
    $countRow = $db->query($countSql, $whereParams)->getRowArray();
    $totalRows = (int) ($countRow['total'] ?? 0);

    $counterSql = "SELECT
        SUM(CASE WHEN d.STATS = 'Pend' THEN 1 ELSE 0 END) AS Pend,
        SUM(CASE WHEN d.STATS IN ('Coll', 'PartColl') THEN 1 ELSE 0 END) AS Coll,
        SUM(CASE WHEN d.STATS IN ('Recv', 'PartRecv') THEN 1 ELSE 0 END) AS Recv,
        SUM(CASE WHEN d.STATS = 'Inc' THEN 1 ELSE 0 END) AS Inc,
        SUM(CASE WHEN d.STATS = 'Fin' THEN 1 ELSE 0 END) AS Fin,
        COUNT(1) AS Total,
        SUM(CASE WHEN r.VAL1USER IS NOT NULL AND r.VAL2USER IS NOT NULL AND ISNULL(r.ISPENDING, 0) <> 1 THEN 1 ELSE 0 END) AS Validated
      FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
      LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER
      WHERE {$baseWhereSql}";
    $counterRow = $db->query($counterSql, $baseParams)->getRowArray() ?? [];

    foreach ($rows as &$row) {
      $row['COLLECTIONDATE'] = date('Y-m-d H:i', strtotime($row['COLLECTIONDATE']));
      $row['REQDATE'] = date('Y-m-d H:i', strtotime($row['REQDATE']));
      $this->normalizeTelephoneFields($row);
    }

    $data = [
      'data' => $rows,
      'pagination' => [
        'page' => $page,
        'pageSize' => $pageSize,
        'totalRows' => $totalRows,
        'totalPages' => max(1, (int) ceil($totalRows / $pageSize)),
      ],
      'counters' => [
        'Pend' => (int) ($counterRow['Pend'] ?? 0),
        'Coll' => (int) ($counterRow['Coll'] ?? 0),
        'Recv' => (int) ($counterRow['Recv'] ?? 0),
        'Inc' => (int) ($counterRow['Inc'] ?? 0),
        'Fin' => (int) ($counterRow['Fin'] ?? 0),
        'Total' => (int) ($counterRow['Total'] ?? 0),
      ],
      'validatedCount' => (int) ($counterRow['Validated'] ?? 0),
    ];

    return $this->response->setJSON($data);
  }

  private function buildBaseWhereClause(string $date1, string $date2, int $userroleid): array
  {
    $where = [
      'd.COLLECTIONDATE BETWEEN ? AND ?',
      'd.ODR_DDATE BETWEEN ? AND ?',
    ];
    $params = [
      $date1 . ' 00:00',
      $date2 . ' 23:59',
      $date1 . ' 00:00',
      $date2 . ' 23:59',
    ];

    if ($userroleid === 2) {
      $where[] = "(d.TESTS IS NOT NULL AND d.TESTS LIKE '%[A-Za-z]%')";
    }

    return [implode(' AND ', $where), $params];
  }

  private function buildDashboardWhereClause(string $baseWhereSql, array $baseParams, string $filterKey, string $search): array
  {
    $where = [$baseWhereSql];
    $params = $baseParams;

    $statusClauses = [
      'Pend' => "d.STATS = 'Pend'",
      'Coll' => "d.STATS IN ('Coll', 'PartColl')",
      'Recv' => "d.STATS IN ('Recv', 'PartRecv')",
      'Inc' => "d.STATS = 'Inc'",
      'Fin' => "d.STATS = 'Fin'",
      'Validated' => 'r.VAL1USER IS NOT NULL AND r.VAL2USER IS NOT NULL AND ISNULL(r.ISPENDING, 0) <> 1',
    ];

    if (isset($statusClauses[$filterKey])) {
      $where[] = $statusClauses[$filterKey];
    }

    if ($search !== '') {
      $where[] = '(d.SP_ACCESSNUMBER LIKE ? OR d.HOSTORDERNUMBER LIKE ? OR d.[Name] LIKE ? OR d.REFF LIKE ? OR d.DOC LIKE ? OR d.TESTS LIKE ? OR d.ODR_CRESULT_TO LIKE ?)';
      $like = '%' . $search . '%';
      $params = [...$params, $like, $like, $like, $like, $like, $like, $like];
    }

    return [implode(' AND ', $where), $params];
  }

  private function resolveSortColumn(string $sortCol): string
  {
    $map = [
      'REQDATE' => 'd.REQDATE',
      'Name' => 'd.[Name]',
      'SP_ACCESSNUMBER' => 'd.SP_ACCESSNUMBER',
      'HOSTORDERNUMBER' => 'd.HOSTORDERNUMBER',
      'REFF' => 'd.REFF',
      'DOC' => 'd.DOC',
      'STATS' => 'd.STATS',
    ];

    return $map[$sortCol] ?? 'd.REQDATE';
  }


  public function show($accessnumber)
  {
    $db = \Config\Database::connect();
    $data['accessnumber'] = $accessnumber;
    $sql = "SELECT d.STATS, r.* FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
      left join GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER
      WHERE d.SP_ACCESSNUMBER='$accessnumber'";
    $result = $db
      ->query($sql)
      ->getResultArray();
    $data['val1'] = $result[0]['ISVAL1'];
    $data['val1user'] = $result[0]['VAL1USER'];
    $data['val2'] = $result[0]['ISVAL2'];
    $data['val2user'] = $result[0]['VAL2USER'];
    return view('admin/modal_request', $data);
  }

  public function showUnval($accessnumber)
  {
    $data['accessnumber'] = $accessnumber;
    return view('admin/modal_unvalidate', $data);
  }

  public function unval($accessnumber)
  {
    $input = $this->request->getJSON(true);
    $userid = session('userid');
    $comment = $input['comment'];
    $db = \Config\Database::connect();
    $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=null, VAL1USER=null, VAL1DATE=null, ISVAL2=null, VAL2USER=null, VAL2DATE=null,
      ISPENDING=1, PENDINGTEXT='$comment', PENDINGUSER='$userid', PENDINGDATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
    $db->query($sql);
    
    $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT, REASON)
                 VALUES (?, 'UNVAL', ?, GETDATE(), ?)";
    $db->query($logAudit, [$accessnumber, $userid, $comment]);
    
    $data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber"];

    return $this->response->setJSON($data);
  }

  public function val($accessnumber)
  {
    $input = $this->request->getJSON(true);
    // Securely get userid from session
    $userid = session('userid');
    $db = \Config\Database::connect();
    $sql = "select * from GDC_CMOD.dbo.CM_REQUESTS where ACCESSNUMBER='$accessnumber'";
    $result = $db->query($sql)->getResultArray();
    if (!isset($result[0])) {
      $sql = "insert into GDC_CMOD.dbo.CM_REQUESTS(ACCESSNUMBER, ISVAL1, VAL1USER, VAL1DATE) VALUES ('$accessnumber', 1, '$userid', GETDATE())";
      $db->query($sql);
      
      $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())";
      $db->query($logAudit, [$accessnumber, $userid]);
      
      $data['val'] = 1;
      $data['userid'] = $userid;
    } else {
      $row = $result[0];
      $isval1 = $row['ISVAL1'];
      $isval2 = $row['ISVAL2'];
      $val1user = $row['VAL1USER'];
      if ($isval1 == 1) {
        if ($isval2 == 1) {
          return $this->response->setJSON(['message' => 'validation done, not updating anything']);
        } else {
          if ($val1user != $userid) {
            $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL2=1, VAL2USER='$userid', VAL2DATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
            
            $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL2', ?, GETDATE())";
            $db->query($logAudit, [$accessnumber, $userid]);
            
            $data['val'] = 2;
            $data['userid'] = $userid;
          } else {
            $this->response->setStatusCode(500);
            return $this->response->setJSON(['message' => 'user already validate this request']);
          }
        }
      } else {
        $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=1, VAL1USER='$userid', VAL1DATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
        
        $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())";
        $db->query($logAudit, [$accessnumber, $userid]);
        
        $data['val'] = 1;
        $data['userid'] = $userid;
      }
      $db->query($sql);
    }

    return $this->response->setJSON($data);
  }

  private function normalizeTelephoneFields(array &$row): void
  {
    foreach (['TELEPHON', 'TELEPHONE'] as $field) {
      if (isset($row[$field]) && is_string($row[$field])) {
        $row[$field] = $this->ensureUtf8($row[$field]);
      }
    }
  }

  private function ensureUtf8(string $value): string
  {
    if (mb_check_encoding($value, 'UTF-8')) {
      return $value;
    }

    $encoding = mb_detect_encoding($value, ['UTF-8', 'CP1252', 'ISO-8859-1'], true);

    return $encoding
      ? mb_convert_encoding($value, 'UTF-8', $encoding)
      : mb_convert_encoding($value, 'UTF-8', 'CP1252');
  }

    public function setEngLanguage($accessnumber)
    {
        $userid = session('userid');
        $db = \Config\Database::connect();

        // Set REPORT_LANG to 1 (English)
        $sql = "UPDATE GDC_CMOD.dbo.CM_REQUESTS SET REPORT_LANG=1 WHERE ACCESSNUMBER='$accessnumber'";
        $db->query($sql);

        // Log the action
        $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'SET_ENG', ?, GETDATE())";
        $db->query($logAudit, [$accessnumber, $userid]);

        // Auto-generate English PDF
        $pdfResult = $this->generateEngPdf($accessnumber);

        return $this->response->setJSON([
            'status' => 'success',
            'message' => 'English result created',
            'pdf' => $pdfResult
        ]);
    }

    private function generateEngPdf(string $accessnumber): array
    {
        $db = \Config\Database::connect();
        $reportHelper = new \App\Libraries\ReportHelper($db);

        $data = $reportHelper->getReportData($accessnumber, 1);
        $data['eng'] = 1;
        $data['accessnumber'] = $accessnumber;
        $data['ispdf'] = 1;

        $html = view('report/template', $data);
        $filename = $accessnumber . '_eng.pdf';

        // Post to spooler
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'http://glenlis:3000/api/pdf/generate');
        curl_setopt($ch, CURLOPT_POST, 1);

$payload = [
            'html' => $html,
            'filename' => $filename,
            'accessnumber' => $accessnumber
        ];

        if (!empty($data['collectionDate'])) {
            $payload['collectionDate'] = $data['collectionDate'];
        }

        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json'
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            log_message('error', "PDF spooler returned HTTP $httpCode for ENG result $accessnumber");
            return ['success' => false, 'error' => 'Failed to queue PDF generation'];
        }

        $responseData = json_decode($response, true);

        // Log PDF generation
        $stepType = 'ENG_PDF';
        $stepStatus = 'English';
        $sqlLog = "INSERT INTO GDC_CMOD.dbo.AUDIT_REQUESTS(ACCESSNUMBER, STEPDATE, STEPTYPE, STEPSTATUS)
                   VALUES (?, GETDATE(), ?, ?)";
        $db->query($sqlLog, [(string)$accessnumber, $stepType, $stepStatus]);

        return [
            'success' => true,
            'jobId' => $responseData['jobId'] ?? null,
            'message' => 'English PDF queued for generation'
        ];
    }

    public function setPdfFlag(string $accessnumber): \CodeIgniter\HTTP\ResponseInterface
    {
        $db = \Config\Database::connect();
        
        $sql = "UPDATE GDC_CMOD.dbo.CM_REQUESTS SET ISPDF = 1 WHERE ACCESSNUMBER = ?";
        $db->query($sql, [$accessnumber]);
        
        $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'PDF_FLAG', 'SYSTEM', GETDATE())";
        $db->query($logAudit, [$accessnumber]);
        
        return $this->response->setJSON([
            'status' => 'success',
            'accessnumber' => $accessnumber
        ]);
    }
}
