import type { McpToolCaller } from "./mcp-tool-client.ts";
import type { PatientCandidate } from "./types.ts";

export interface AdvancedMdReadGateway {
  authStatus(): Promise<unknown>;
  searchPatients(searchterm: string): Promise<PatientCandidate[]>;
  getAppointmentHistory(patientId: string): Promise<unknown>;
  getVisitInfoByDate(visitdate: string): Promise<unknown>;
  getFieldsetInfo(): Promise<unknown>;
}

interface AmdRowsResponse {
  rows?: Array<Record<string, unknown>>;
}

export class AdvancedMdMcpReadGateway implements AdvancedMdReadGateway {
  constructor(private readonly mcp: McpToolCaller) {}

  authStatus(): Promise<unknown> {
    return this.mcp.callTool("auth_status");
  }

  async searchPatients(searchterm: string): Promise<PatientCandidate[]> {
    const result = (await this.mcp.callTool("search_patients", {
      searchterm,
    })) as AmdRowsResponse;
    return (result.rows ?? [])
      .map(patientCandidateFromAmdRow)
      .filter((candidate): candidate is PatientCandidate => Boolean(candidate));
  }

  getAppointmentHistory(patientId: string): Promise<unknown> {
    return this.mcp.callTool("get_appointment_history", { patientid: patientId });
  }

  getVisitInfoByDate(visitdate: string): Promise<unknown> {
    return this.mcp.callTool("get_visit_info_by_date", { visitdate });
  }

  getFieldsetInfo(): Promise<unknown> {
    return this.mcp.callTool("get_fieldset_info");
  }
}

function patientCandidateFromAmdRow(row: Record<string, unknown>): PatientCandidate | undefined {
  const patientId = stringValue(row.id ?? row.patientid ?? row.patient_id);
  const legalName = stringValue(row.name ?? row.patient_name ?? row.Name);
  const dob = stringValue(row.dob ?? row.DOB ?? row.dateofbirth);
  if (!patientId || !legalName || !dob) return undefined;

  const phones = [
    row.phone,
    row.homephone,
    row.mobilephone,
    row.cellphone,
    row.patient_phone,
  ]
    .map(stringValue)
    .filter((value): value is string => Boolean(value));

  return {
    patientId,
    legalName,
    dob,
    phones,
  };
}

function stringValue(value: unknown): string | undefined {
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
}
