/**
 * Client HTTP minimal vers l'API MCP Joseph (`routes/api.php`, préfixe
 * `mcp/v1`) — lecture seule pour l'instant (voir CLAUDE.md/plan du
 * chantier). Un jeton Sanctum personnel (`JOSEPH_API_TOKEN`, généré par
 * `php artisan joseph:mcp-token`) est envoyé en `Authorization: Bearer`.
 */

export interface JosephConfig {
  baseUrl: string;
  token: string;
}

export class JosephApiError extends Error {
  constructor(
    public readonly status: number,
    message: string,
  ) {
    super(message);
    this.name = "JosephApiError";
  }
}

async function request<T>(config: JosephConfig, path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T> {
  const url = new URL(`/api/mcp/v1${path}`, config.baseUrl);

  if (params) {
    for (const [key, value] of Object.entries(params)) {
      if (value !== undefined) {
        url.searchParams.set(key, String(value));
      }
    }
  }

  const response = await fetch(url, {
    headers: {
      Authorization: `Bearer ${config.token}`,
      Accept: "application/json",
    },
  });

  if (!response.ok) {
    const body = await response.text();
    throw new JosephApiError(response.status, `${response.status} ${response.statusText} sur ${path} — ${body.slice(0, 500)}`);
  }

  return (await response.json()) as T;
}

export interface Workspace {
  id: number;
  name: string;
  slug: string;
}

export interface ProjectPerson {
  name: string;
  role: string;
}

export interface Project {
  code: string;
  name: string;
  description: string | null;
  status: string;
  start_date: string | null;
  target_end_date: string | null;
  people?: ProjectPerson[];
}

export interface ElementType {
  code: string;
  label: string;
}

export interface ElementStatus {
  code: string;
  label: string;
  category: string;
}

export interface ElementAssignee {
  id: number;
  name: string;
  role: string;
}

export interface Element {
  code: string;
  title: string;
  description: string | null;
  priority: string | null;
  due_date: string | null;
  position: number;
  type: ElementType;
  status: ElementStatus;
  children_count?: number;
  assignees?: ElementAssignee[];
  ancestors?: { code: string; title: string }[];
  project?: { code: string; name: string };
}

export interface Meeting {
  code: string;
  title: string;
  status: ElementStatus;
  starts_at: string | null;
  ends_at: string | null;
  timezone: string | null;
  is_all_day: boolean | null;
  location: string | null;
  online_meeting_url: string | null;
  agenda: string | null;
  is_cancelled: boolean | null;
  is_recurring: boolean | null;
  has_minutes: boolean;
  organizer: string | null;
  attendees?: { name: string | null; response_status: string | null }[];
}

interface Collection<T> {
  data: T[];
}

interface Single<T> {
  data: T;
}

export class JosephClient {
  constructor(private readonly config: JosephConfig) {}

  listWorkspaces(): Promise<Collection<Workspace>> {
    return request(this.config, "/workspaces");
  }

  listProjects(workspaceId: number): Promise<Collection<Project>> {
    return request(this.config, `/workspaces/${workspaceId}/projects`);
  }

  getProject(workspaceId: number, projectCode: string): Promise<Single<Project>> {
    return request(this.config, `/workspaces/${workspaceId}/projects/${encodeURIComponent(projectCode)}`);
  }

  listElements(workspaceId: number, projectCode: string, parentCode?: string): Promise<Collection<Element>> {
    return request(this.config, `/workspaces/${workspaceId}/projects/${encodeURIComponent(projectCode)}/elements`, {
      parent_code: parentCode,
    });
  }

  getElement(workspaceId: number, elementCode: string): Promise<Single<Element>> {
    return request(this.config, `/workspaces/${workspaceId}/elements/${encodeURIComponent(elementCode)}`);
  }

  listMeetings(workspaceId: number, projectCode: string, upcomingOnly?: boolean): Promise<Collection<Meeting>> {
    return request(this.config, `/workspaces/${workspaceId}/projects/${encodeURIComponent(projectCode)}/meetings`, {
      upcoming: upcomingOnly,
    });
  }

  listMyDeadlines(workspaceId: number, withinDays?: number): Promise<Collection<Element>> {
    return request(this.config, `/workspaces/${workspaceId}/me/deadlines`, {
      within_days: withinDays,
    });
  }
}
