import { get, post, patch, del } from '@/lib/api-client';

const BASE_URL = '/site-attendance';

// --- Types ---

export interface Checkpoint {
  id: string;
  code: string;
  name: string;
  description?: string;
  address?: string;
  timezone: string;
  latitude: number;
  longitude: number;
  geoPolicy: 'STRICT_BLOCK' | 'ALLOW_WITH_FLAG' | 'SKIP';
  geoRadius: number;
  geoAccuracyThreshold: number;
  allowUnauthenticatedCheckin: boolean;
  isActive: boolean;
  createdAt: string;
}

export type AccessMode = 'PUBLIC' | 'SIGNED';

export interface PublicCheckpoint {
  id: string;
  name: string;
  description?: string;
  address?: string;
  timezone: string;
  geoPolicy: 'STRICT_BLOCK' | 'ALLOW_WITH_FLAG' | 'SKIP';
  geoRadius?: number;
  allowUnauthenticatedCheckin: boolean;
  // v1.5
  accessMode?: AccessMode;
  sharedCheckinEnabled?: boolean;
  sharedCompanyId?: string;
  sharedCompanyLabel?: string;
}

// v1.5 shared check-in types

export interface SharedCheckinPartner {
  id: string;
  companyId: string;
  companyLabel: string;
  displayLabel?: string | null;
  targetUrl: string;
  isActive: boolean;
  sortOrder: number;
  updatedAt: string;
}

export interface DispatchOptionSelf {
  companyId: string;
  companyLabel: string;
  checkpointCode: string;
  checkpointName: string;
}

export interface DispatchOptionPartner {
  partnerId: string;
  companyId: string;
  companyLabel: string;
  displayLabel?: string;
  isExternal: boolean;
}

export interface DispatchOptions {
  self: DispatchOptionSelf;
  partners: DispatchOptionPartner[];
}

export interface QrTokenResponse {
  token: string;
  expiresAt: number | null;
  scope: 'checkpoint' | 'shared';
  rotationSeconds: number | null;
  graceSeconds: number;
}

export interface DispatchRequest {
  checkpointCode: string;
  qrToken: string;
  choice: {
    companyId: string;
    partnerId?: string;
  };
}

export interface DispatchResult {
  redirectUrl: string;
  ticketExpiresAt: number;
  targetMode: 'local' | 'external';
}

export interface ValidateTicketResult {
  valid: true;
  payload: {
    companyId: string;
    dispatchOrigin: string;
    expiresAt: number;
  };
}

export interface CreatePartnerDto {
  companyId: string;
  companyLabel: string;
  displayLabel?: string;
  targetUrl: string;
  isActive?: boolean;
  sortOrder?: number;
}

export interface SearchUser {
  id: string;
  displayName: string;
  email: string;
  department?: string;
}

export type EventType = 'CHECK_IN' | 'CHECK_OUT';
export type GeoStatus =
  | 'VALID'
  | 'OUT_OF_RANGE'
  | 'LOW_ACCURACY'
  | 'PERMISSION_DENIED'
  | 'UNAVAILABLE'
  | 'TIMEOUT'
  | 'SKIPPED';

export interface AttendanceEvent {
  id: string;
  eventType: EventType;
  timestamp: string;
  geoStatus: GeoStatus;
  authMethod: 'AUTHENTICATED' | 'UNAUTHENTICATED';
  latitude?: number | null;
  longitude?: number | null;
  accuracy?: number | null;
  distanceToCheckpoint?: number | null;
}

export interface TodaySummary {
  firstCheckIn?: string | null;
  lastCheckOut?: string | null;
  totalEvents: number;
  todayDurationSeconds: number;
}

export interface CheckinResult {
  event: {
    id: string;
    eventType: EventType;
    timestamp: string;
    geoStatus: GeoStatus;
    distanceToCheckpoint?: number;
  };
  todaySummary: TodaySummary;
}

export interface CheckinPayload {
  eventType: EventType;
  latitude?: number;
  longitude?: number;
  accuracy?: number;
  geoStatus: GeoStatus;
  deviceId?: string;
}

export interface GuestCheckinPayload extends CheckinPayload {
  userId: string;
}

export interface CreateCheckpointDto {
  name: string;
  description?: string;
  address?: string;
  timezone: string;
  latitude: number;
  longitude: number;
  geoPolicy?: 'STRICT_BLOCK' | 'ALLOW_WITH_FLAG' | 'SKIP';
  geoRadius?: number;
  geoAccuracyThreshold?: number;
  allowUnauthenticatedCheckin?: boolean;
  // v1.5
  accessMode?: AccessMode;
  qrRotationSeconds?: number | null;
  qrGraceSeconds?: number;
  sharedCheckinEnabled?: boolean;
  sharedCompanyId?: string;
  sharedCompanyLabel?: string;
}

// --- API Methods ---

export const siteAttendanceApi = {
  // Public endpoints
  getPublicCheckpoint: (code: string, qrToken?: string, ticket?: string) => {
    const params: Record<string, string> = {};
    if (qrToken) params.t = qrToken;
    if (ticket) params.ticket = ticket;
    return get<PublicCheckpoint>(
      `${BASE_URL}/checkpoints/code/${code}/public`,
      Object.keys(params).length > 0 ? { params } : undefined,
    );
  },

  searchUsers: (code: string, query: string) =>
    get<{ users: SearchUser[] }>(
      `${BASE_URL}/checkpoints/code/${code}/user-search`,
      { params: { q: query } },
    ),

  getTodayEvents: (code: string, userId: string) =>
    get<{ events: AttendanceEvent[]; summary: TodaySummary }>(
      `${BASE_URL}/checkpoints/code/${code}/today-events`,
      { params: { userId } },
    ),

  checkin: (code: string, payload: CheckinPayload) =>
    post<CheckinResult>(
      `${BASE_URL}/checkpoints/code/${code}/checkin`,
      payload,
    ),

  guestCheckin: (code: string, payload: GuestCheckinPayload) =>
    post<CheckinResult>(
      `${BASE_URL}/checkpoints/code/${code}/guest-checkin`,
      payload,
    ),

  // Admin endpoints
  listCheckpoints: () =>
    get<{ checkpoints: Checkpoint[] }>(`${BASE_URL}/checkpoints`),

  createCheckpoint: (data: CreateCheckpointDto) =>
    post<Checkpoint>(`${BASE_URL}/checkpoints`, data),

  getCheckpoint: (id: string) =>
    get<Checkpoint>(`${BASE_URL}/checkpoints/${id}`),

  updateCheckpoint: (id: string, data: Partial<CreateCheckpointDto> & { isActive?: boolean }) =>
    patch<Checkpoint>(`${BASE_URL}/checkpoints/${id}`, data),

  deleteCheckpoint: (id: string) =>
    del(`${BASE_URL}/checkpoints/${id}`),

  getCheckpointEvents: (
    id: string,
    params?: { date?: string; page?: number; pageSize?: number; userName?: string; eventType?: string; lang?: string },
  ) =>
    get<{
      events: Array<{
        id: string;
        userId: string;
        userName: string;
        userEmail: string;
        eventType: EventType;
        timestamp: string;
        authMethod: string;
        geoStatus: GeoStatus;
        latitude?: number | null;
        longitude?: number | null;
        accuracy?: number | null;
        distanceToCheckpoint?: number;
        resolvedAddress?: string | null;
      }>;
      pagination: { total: number; page: number; pageSize: number };
    }>(`${BASE_URL}/checkpoints/${id}/events`, { params }),

  exportEvents: (id: string, date?: string) =>
    `${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/v1'}${BASE_URL}/checkpoints/${id}/events/export${date ? `?date=${date}` : ''}`,

  getTodaySummaryAdmin: (id: string) =>
    get<{
      date: string;
      totalCheckedIn: number;
      totalCheckedOut: number;
      notCheckedOut: number;
      totalDurationSeconds: number;
      avgDurationSeconds: number;
      recentEvents: Array<{
        userId: string;
        userName: string;
        eventType: string;
        timestamp: string;
      }>;
    }>(`${BASE_URL}/checkpoints/${id}/today-summary`),

  // --- v1.5 shared checkin ---

  getQrToken: (code: string) =>
    get<QrTokenResponse>(`${BASE_URL}/checkpoints/code/${code}/qr-token`),

  getDispatchOptions: (code: string, qrToken: string) =>
    get<DispatchOptions>(
      `${BASE_URL}/checkpoints/code/${code}/dispatch-options`,
      { params: { t: qrToken } },
    ),

  dispatch: (req: DispatchRequest) =>
    post<DispatchResult>(`${BASE_URL}/shared-checkin/dispatch`, req),

  validateTicket: (ticket: string, targetCheckpointCode: string) =>
    post<ValidateTicketResult>(`${BASE_URL}/shared-checkin/validate-ticket`, {
      ticket,
      targetCheckpointCode,
    }),

  listPartners: (checkpointId: string) =>
    get<{ partners: SharedCheckinPartner[] }>(
      `${BASE_URL}/checkpoints/${checkpointId}/partners`,
    ),

  createPartner: (checkpointId: string, dto: CreatePartnerDto) =>
    post<SharedCheckinPartner>(
      `${BASE_URL}/checkpoints/${checkpointId}/partners`,
      dto,
    ),

  updatePartner: (partnerId: string, dto: Partial<CreatePartnerDto>) =>
    patch<SharedCheckinPartner>(`${BASE_URL}/partners/${partnerId}`, dto),

  deletePartner: (partnerId: string) =>
    del(`${BASE_URL}/partners/${partnerId}`),
};
