unit Api.ServiceImpl;

interface

uses
  XData.Server.Module, XData.Service.Common, Api.Database, Data.DB,
  System.SysUtils, System.Generics.Collections, XData.Sys.Exceptions, System.StrUtils,
  System.Hash, System.Classes, Common.Logging, System.JSON, Api.Service, VCL.Forms;


type
  [ServiceImplementation]
  TApiService = class(TInterfacedObject, IApiService)
  strict private
  ApiDB: TApiDatabaseModule;
  private
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  public
    function GetComplaintList: TJSONObject;
    function GetUnitList: TJSONObject;
  end;

implementation

uses
  uLibrary;

procedure TApiService.AfterConstruction;
begin
  inherited;
  ApiDB := TApiDatabaseModule.Create(nil);
  Logger.Log(3, 'ApiDatabaseModule created');
end;

procedure TApiService.BeforeDestruction;
begin
  ApiDB.Free;
  inherited;
  Logger.Log(3, 'ApiDatabaseModule destroyed');
end;

function TApiService.GetComplaintList: TJSONObject;
var
  data: TJSONArray;
  lastDistrict: string;
begin
  Logger.Log(3, '---TApiService.GetComplaintList initiated');

  Result := TJSONObject.Create;
  TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);

  data := TJSONArray.Create;
  try
    lastDistrict := '';
    with ApiDB.uqComplaintList do
    begin
      Open;
      First;
      while not Eof do
      begin
        var status: string;
        if not FieldByName('DATECLEARED').IsNull then
          status := 'Cleared'
        else if not FieldByName('DATEARRIVED').IsNull then
          status := 'AtScene'
        else if not FieldByName('DATEDISPATCHED').IsNull then
          status := 'Dispatched'
        else
          status := 'Pending';

        var item := TJSONObject.Create;

        // Add a section header only when the district changes
        var curDistrict := ApiDB.uqComplaintListDISPATCHDISTRICT.AsString;
        if not SameText(curDistrict, lastDistrict) then
          item.AddPair('DistrictHeader', curDistrict);
        lastDistrict := curDistrict;

        var districtSector := ApiDB.uqComplaintListDISTRICT_DESC.AsString + ApiDB.uqComplaintListSECTOR_DESC.AsString;
        item.AddPair('DistrictSector', districtSector);

        // existing color hex
        var colorVal := ApiDB.uqComplaintListPRIORITY_COLOR.AsInteger;
        item.AddPair('PriorityColor', '#' + IntToHex(colorVal and $FFFFFF, 6));

        // Text is white only for the deep blue (255 = $0000FF), black otherwise
        if (colorVal and $FFFFFF) = $0000FF then
          item.AddPair('PriorityTextColor', '#FFFFFF')
        else
          item.AddPair('PriorityTextColor', '#000000');

        item.AddPair('ComplaintId', ApiDB.uqComplaintListCOMPLAINTID.AsString);
        item.AddPair('Complaint', ApiDB.uqComplaintListcomplaintNumber.AsString);
        item.AddPair('Agency', ApiDB.uqComplaintListAGENCY.AsString);
        item.AddPair('Priority', ApiDB.uqComplaintListPRIORITY.AsString);
        item.AddPair('DispatchCodeDesc', ApiDB.uqComplaintListDISPATCH_CODE_DESC.AsString);
        item.AddPair('Address', ApiDB.uqComplaintListADDRESS.AsString);
        item.AddPair('CFSId', ApiDB.uqComplaintListCFSID.AsString);
        item.AddPair('Status', status);
        item.AddPair('DispatchDistrict', curDistrict);
        item.AddPair('DateReported', ApiDB.uqComplaintListDATEREPORTED.AsString);

        data.AddElement(item);
        Next;
      end;
    end;

    Result.AddPair('count', TJSONNumber.Create(data.Count));
    Result.AddPair('returned', TJSONNumber.Create(data.Count));
    Result.AddPair('data', data);
  except
    data.Free;
    Logger.Log(3, '---TApiService.GetComplaintList End (error)');
    raise EXDataHttpException.Create(500, 'Failed to load complaints list');
  end;

  Logger.Log(3, '---TApiService.GetComplaintList End');
end;


function TApiService.GetUnitList: TJSONObject;
var
  data: TJSONArray;
  lastDistrict: string;
begin
  Logger.Log(3, '---TApiService.GetUnitList initiated');

  Result := TJSONObject.Create;
  TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);

  data := TJSONArray.Create;
  try
    lastDistrict := '';
    with ApiDB.uqDISUnitsActive do
    begin
      Open;
      First;
      while not Eof do
      begin
        var item := TJSONObject.Create;

        // Group header: show once when district changes (e.g., "1", "A")
        var curDistrict := ApiDB.uqDISUnitsActiveDISTRICT_DESC.AsString;
        if not SameText(curDistrict, lastDistrict) then
          item.AddPair('DistrictHeader', curDistrict);
        lastDistrict := curDistrict;

        // Core unit identity
        item.AddPair('UnitId',         ApiDB.uqDISUnitsActiveUNITID.AsString);
        item.AddPair('UnitName',       ApiDB.uqDISUnitsActiveUNITNAME.AsString);
        item.AddPair('CarNumberDesc',  ApiDB.uqDISUnitsActiveCARNUMBER_DESC.AsString);
        item.AddPair('District',       curDistrict);
        item.AddPair('Sector',         ApiDB.uqDISUnitsActiveSECTOR_DESC.AsString);

        // Current assignment (if any)
        item.AddPair('Location',       ApiDB.uqDISUnitsActiveLOCATION.AsString);
        item.AddPair('Complaint',      ApiDB.uqDISUnitsActiveCOMPLAINT.AsString);

        // Status: default to "Available" when no active CFS row
       var statusDesc := ApiDB.uqDISUnitsActiveUNIT_STATUS_DESC.AsString;
       if statusDesc = '' then
         statusDesc := 'Available';
       item.AddPair('Status', statusDesc);

        // Officers (LAST, FIRST [MI])
        var o1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_LAST_NAME.AsString);
        var f1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_FIRST_NAME.AsString);
        var m1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_MI.AsString);
        if o1 <> '' then
        begin
          if f1 <> '' then o1 := o1 + ', ' + f1;
          if m1 <> '' then o1 := o1 + ' ' + m1;
          item.AddPair('Officer1', o1);
        end;

        var o2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_LAST_NAME.AsString);
        var f2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_FIRST_NAME.AsString);
        var m2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_MI.AsString);
        if o2 <> '' then
        begin
          if f2 <> '' then o2 := o2 + ', ' + f2;
          if m2 <> '' then o2 := o2 + ' ' + m2;
          item.AddPair('Officer2', o2);
        end;

        data.AddElement(item);
        Next;
      end;
    end;

    Result.AddPair('count',    TJSONNumber.Create(data.Count));
    Result.AddPair('returned', TJSONNumber.Create(data.Count));
    Result.AddPair('data',     data);
  except
    data.Free;
    Logger.Log(3, '---TApiService.GetUnitList End (error)');
    raise EXDataHttpException.Create(500, 'Failed to load units list');
  end;

  Logger.Log(3, '---TApiService.GetUnitList End');
end;





initialization
  RegisterServiceType(TApiService);

end.

