<?php

namespace App\Models\Contact;

use App\Models\BaseModel;

class ContactDetailModel extends BaseModel {
  protected $table      = 'contactdetail';
  protected $primaryKey = 'ContactDetID';
  protected $allowedFields = ['ContactID', 'SiteID', 'ContactCode', 'ContactEmail', 'OccupationID', 'JobTitle', 'Department', 'ContactStartDate', 'ContactEndDate']; 
  
  protected $useTimestamps = true;
  protected $createdField = 'ContactStartDate';
  protected $updatedField = '';
  protected $useSoftDeletes = true;
  protected $deletedField = 'ContactEndDate';

  public function syncDetails(int $ContactID, array $contactDetails) {
    try {
      $keptSiteIDs = [];

      foreach ($contactDetails as $detail) {
        if (empty($detail['SiteID'])) {
          continue;
        }

        $detail['ContactID'] = $ContactID;

        $existing = $this->where('ContactID', $ContactID)
          ->where('SiteID', $detail['SiteID'])
          ->first();

        if ($existing) {
          $this->update($existing[$this->primaryKey], $detail);
        } else {
          $this->insert($detail);
        }

        $keptSiteIDs[] = $detail['SiteID'];
      }

      // Delete missing rows
      if (!empty($keptSiteIDs)) {
        $this->where('ContactID', $ContactID)
          ->whereNotIn('SiteID', $keptSiteIDs)
          ->delete();
      } else {
        $this->where('ContactID', $ContactID)->delete();
      }

      return [
        'status'   => 'success',
        'inserted' => count($contactDetails) - count($keptSiteIDs),
        'kept'     => count($keptSiteIDs),
      ];
    } catch (\Throwable $e) {
        log_message('error', 'syncDetails error: ' . $e->getMessage());

        return [
          'status'  => 'error',
          'message' => $e->getMessage(),
        ];
    }
}

  public function applyDetailOperations(int $contactID, array $operations): array
  {
    try {
      if (!empty($operations['edited']) && !$this->updateDetails($contactID, $operations['edited'])) {
        return ['status' => 'error', 'message' => $this->lastDetailError ?? 'Failed to update contact details'];
      }

      if (!empty($operations['deleted']) && !$this->softDeleteDetails($contactID, $operations['deleted'])) {
        return ['status' => 'error', 'message' => 'Failed to delete contact details'];
      }

      if (!empty($operations['created']) && !$this->insertDetailRows($contactID, $operations['created'])) {
        return ['status' => 'error', 'message' => 'Failed to create contact details'];
      }

      return ['status' => 'success'];
    } catch (\Throwable $e) {
      log_message('error', 'applyDetailOperations error: ' . $e->getMessage());

      return [
        'status'  => 'error',
        'message' => $e->getMessage(),
      ];
    }
  }

  private function insertDetailRows(int $contactID, array $items): bool
  {
    foreach ($items as $item) {
      if (!is_array($item)) {
        return false;
      }

      $item['ContactID'] = $contactID;
      $this->insert($item);
    }

    return true;
  }

  private function updateDetails(int $contactID, array $items): bool
  {
    foreach ($items as $detail) {
      $detailID = $detail['ContactDetID'] ?? null;
      if (!$detailID || !ctype_digit((string) $detailID)) {
        $this->lastDetailError = 'ContactDetID is required and must be an integer.';
        return false;
      }

      $existing = $this->where('ContactDetID', (int) $detailID)
        ->where('ContactID', $contactID)
        ->where('ContactEndDate', null)
        ->first();

      if (empty($existing)) {
        $this->lastDetailError = "Detail record {$detailID} not found for Contact {$contactID}.";
        return false;
      }

      $updateData = array_intersect_key($detail, array_flip($this->allowedFields));
      unset($updateData['ContactID']);

      if ($updateData !== [] && !$this->update((int) $detailID, $updateData)) {
        $dbError = $this->db->error();
        $this->lastDetailError = sprintf(
          'Failed to update detail %d for Contact %d%s',
          (int) $detailID,
          $contactID,
          !empty($dbError['message']) ? ': ' . $dbError['message'] : ''
        );
        return false;
      }
    }

    return true;
  }

  private ?string $lastDetailError = null;

  private function softDeleteDetails(int $contactID, array $ids): bool
  {
    $ids = array_values(array_unique(array_map('intval', $ids)));
    if ($ids === []) {
      return true;
    }

    $existing = $this->select('ContactDetID')
      ->whereIn('ContactDetID', $ids)
      ->where('ContactID', $contactID)
      ->findAll();

    if (count($existing) !== count($ids)) {
      return false;
    }

    $this->whereIn('ContactDetID', $ids)
      ->where('ContactID', $contactID)
      ->delete();

    return true;
  }
}
