import { z } from 'zod';

// ============================================================================
// Branded ID Types
// ============================================================================

export type BaseId = string & { readonly __brand: 'BaseId' };
export type TableId = string & { readonly __brand: 'TableId' };
export type RecordId = string & { readonly __brand: 'RecordId' };
export type FieldId = string & { readonly __brand: 'FieldId' };
export type ViewId = string & { readonly __brand: 'ViewId' };
export type WebhookId = string & { readonly __brand: 'WebhookId' };
export type AutomationId = string & { readonly __brand: 'AutomationId' };

export const BaseIdSchema = z.string().transform((v) => v as BaseId);
export const TableIdSchema = z.string().transform((v) => v as TableId);
export const RecordIdSchema = z.string().transform((v) => v as RecordId);
export const FieldIdSchema = z.string().transform((v) => v as FieldId);
export const ViewIdSchema = z.string().transform((v) => v as ViewId);
export const WebhookIdSchema = z.string().transform((v) => v as WebhookId);
export const AutomationIdSchema = z.string().transform((v) => v as AutomationId);

// ============================================================================
// Field Types
// ============================================================================

export type FieldType =
  | 'singleLineText'
  | 'email'
  | 'url'
  | 'multilineText'
  | 'number'
  | 'percent'
  | 'currency'
  | 'singleSelect'
  | 'multipleSelects'
  | 'singleCollaborator'
  | 'multipleCollaborators'
  | 'multipleRecordLinks'
  | 'date'
  | 'dateTime'
  | 'phoneNumber'
  | 'multipleAttachments'
  | 'checkbox'
  | 'formula'
  | 'createdTime'
  | 'rollup'
  | 'count'
  | 'lookup'
  | 'multipleLookupValues'
  | 'autoNumber'
  | 'barcode'
  | 'rating'
  | 'richText'
  | 'duration'
  | 'lastModifiedTime'
  | 'button'
  | 'createdBy'
  | 'lastModifiedBy'
  | 'externalSyncSource'
  | 'aiText';

export const FieldTypeSchema = z.enum([
  'singleLineText',
  'email',
  'url',
  'multilineText',
  'number',
  'percent',
  'currency',
  'singleSelect',
  'multipleSelects',
  'singleCollaborator',
  'multipleCollaborators',
  'multipleRecordLinks',
  'date',
  'dateTime',
  'phoneNumber',
  'multipleAttachments',
  'checkbox',
  'formula',
  'createdTime',
  'rollup',
  'count',
  'lookup',
  'multipleLookupValues',
  'autoNumber',
  'barcode',
  'rating',
  'richText',
  'duration',
  'lastModifiedTime',
  'button',
  'createdBy',
  'lastModifiedBy',
  'externalSyncSource',
  'aiText',
]);

// ============================================================================
// Field Configuration
// ============================================================================

export interface SelectOption {
  id: string;
  name: string;
  color?: string;
}

export interface Collaborator {
  id: string;
  email: string;
  name?: string;
}

export interface CurrencyOptions {
  precision: number;
  symbol: string;
}

export interface NumberOptions {
  precision: number;
}

export interface PercentOptions {
  precision: number;
}

export interface RatingOptions {
  icon: string;
  max: number;
  color?: string;
}

export interface DurationOptions {
  durationFormat: 'h:mm' | 'h:mm:ss' | 'h:mm:ss.S' | 'h:mm:ss.SS' | 'h:mm:ss.SSS';
}

export interface DateOptions {
  dateFormat: {
    name: 'local' | 'friendly' | 'us' | 'european' | 'iso';
    format: string;
  };
}

export interface DateTimeOptions {
  dateFormat: {
    name: 'local' | 'friendly' | 'us' | 'european' | 'iso';
    format: string;
  };
  timeFormat: {
    name: '12hour' | '24hour';
    format: string;
  };
  timeZone: string;
}

export interface Field {
  id: FieldId;
  name: string;
  type: FieldType;
  description?: string;
  options?: {
    choices?: SelectOption[];
    linkedTableId?: TableId;
    prefersSingleRecordLink?: boolean;
    inverseLinkFieldId?: FieldId;
    isReversed?: boolean;
    precision?: number;
    symbol?: string;
    icon?: string;
    max?: number;
    color?: string;
    durationFormat?: string;
    dateFormat?: unknown;
    timeFormat?: unknown;
    timeZone?: string;
    result?: unknown;
    formula?: string;
    recordLinkFieldId?: FieldId;
    fieldIdInLinkedTable?: FieldId;
    referencedFieldIds?: FieldId[];
  };
}

export const FieldSchema = z.object({
  id: FieldIdSchema,
  name: z.string(),
  type: FieldTypeSchema,
  description: z.string().optional(),
  options: z.record(z.unknown()).optional(),
});

// ============================================================================
// Attachments and Thumbnails
// ============================================================================

export interface Thumbnail {
  url: string;
  width: number;
  height: number;
}

export interface Attachment {
  id: string;
  url: string;
  filename: string;
  size: number;
  type: string;
  width?: number;
  height?: number;
  thumbnails?: {
    small?: Thumbnail;
    large?: Thumbnail;
    full?: Thumbnail;
  };
}

export const ThumbnailSchema = z.object({
  url: z.string(),
  width: z.number(),
  height: z.number(),
});

export const AttachmentSchema = z.object({
  id: z.string(),
  url: z.string(),
  filename: z.string(),
  size: z.number(),
  type: z.string(),
  width: z.number().optional(),
  height: z.number().optional(),
  thumbnails: z
    .object({
      small: ThumbnailSchema.optional(),
      large: ThumbnailSchema.optional(),
      full: ThumbnailSchema.optional(),
    })
    .optional(),
});

// ============================================================================
// Records
// ============================================================================

export type RecordFields = globalThis.Record<string, unknown>;

export interface AirtableRecord {
  id: RecordId;
  createdTime: string;
  fields: RecordFields;
}

export const AirtableRecordSchema = z.object({
  id: RecordIdSchema,
  createdTime: z.string(),
  fields: z.record(z.unknown()),
});

// ============================================================================
// Tables
// ============================================================================

export interface Table {
  id: TableId;
  name: string;
  description?: string;
  primaryFieldId: FieldId;
  fields: Field[];
  views: View[];
}

export const TableSchema = z.object({
  id: TableIdSchema,
  name: z.string(),
  description: z.string().optional(),
  primaryFieldId: FieldIdSchema,
  fields: z.array(FieldSchema),
  views: z.array(z.lazy(() => ViewSchema)),
});

// ============================================================================
// Views
// ============================================================================

export type ViewType = 'grid' | 'form' | 'calendar' | 'gallery' | 'kanban' | 'timeline' | 'gantt';

export const ViewTypeSchema = z.enum(['grid', 'form', 'calendar', 'gallery', 'kanban', 'timeline', 'gantt']);

export interface View {
  id: ViewId;
  name: string;
  type: ViewType;
}

export const ViewSchema = z.object({
  id: ViewIdSchema,
  name: z.string(),
  type: ViewTypeSchema,
});

// ============================================================================
// Bases
// ============================================================================

export interface Base {
  id: BaseId;
  name: string;
  permissionLevel: 'none' | 'read' | 'comment' | 'edit' | 'create';
}

export const BaseSchema = z.object({
  id: BaseIdSchema,
  name: z.string(),
  permissionLevel: z.enum(['none', 'read', 'comment', 'edit', 'create']),
});

// ============================================================================
// Webhooks
// ============================================================================

export interface WebhookPayload {
  baseTransactionNumber?: number;
  timestamp?: string;
  actionMetadata?: {
    source: string;
    sourceMetadata?: unknown;
  };
  changedTablesById?: globalThis.Record<
    string,
    {
      createdRecordsById?: globalThis.Record<string, unknown>;
      changedRecordsById?: globalThis.Record<string, unknown>;
      destroyedRecordIds?: string[];
      createdFieldsById?: globalThis.Record<string, unknown>;
      changedFieldsById?: globalThis.Record<string, unknown>;
      destroyedFieldIds?: string[];
      changedViewsById?: globalThis.Record<string, unknown>;
      createdViewsById?: globalThis.Record<string, unknown>;
      destroyedViewIds?: string[];
      changedMetadata?: unknown;
    }
  >;
}

export interface Webhook {
  id: WebhookId;
  macSecretBase64?: string;
  expirationTime?: string;
  specification?: {
    options: {
      filters: {
        dataTypes: Array<'tableData' | 'tableFields' | 'tableMetadata'>;
        recordChangeScope?: string;
        watchDataInFieldIds?: string[];
        watchSchemasOfFieldIds?: string[];
        sourceOptions?: unknown;
      };
      includes?: {
        includeCellValuesInFieldIds?: string[] | 'all';
        includePreviousCellValues?: boolean;
        includePreviousFieldDefinitions?: boolean;
      };
    };
  };
}

export const WebhookSchema = z.object({
  id: WebhookIdSchema,
  macSecretBase64: z.string().optional(),
  expirationTime: z.string().optional(),
  specification: z
    .object({
      options: z.object({
        filters: z.object({
          dataTypes: z.array(z.enum(['tableData', 'tableFields', 'tableMetadata'])),
          recordChangeScope: z.string().optional(),
          watchDataInFieldIds: z.array(z.string()).optional(),
          watchSchemasOfFieldIds: z.array(z.string()).optional(),
          sourceOptions: z.unknown().optional(),
        }),
        includes: z
          .object({
            includeCellValuesInFieldIds: z.union([z.array(z.string()), z.literal('all')]).optional(),
            includePreviousCellValues: z.boolean().optional(),
            includePreviousFieldDefinitions: z.boolean().optional(),
          })
          .optional(),
      }),
    })
    .optional(),
});

// ============================================================================
// Automations
// ============================================================================

export interface AutomationTrigger {
  type: string;
  config: unknown;
}

export interface AutomationAction {
  type: string;
  config: unknown;
}

export interface Automation {
  id: AutomationId;
  name: string;
  state: 'active' | 'disabled';
  trigger: AutomationTrigger;
  actions: AutomationAction[];
  createdTime: string;
}

export const AutomationSchema = z.object({
  id: AutomationIdSchema,
  name: z.string(),
  state: z.enum(['active', 'disabled']),
  trigger: z.object({
    type: z.string(),
    config: z.unknown(),
  }),
  actions: z.array(
    z.object({
      type: z.string(),
      config: z.unknown(),
    })
  ),
  createdTime: z.string(),
});

// ============================================================================
// Comments
// ============================================================================

export interface Comment {
  id: string;
  text: string;
  createdTime: string;
  author: {
    id: string;
    email: string;
    name?: string;
  };
  lastUpdatedTime?: string;
  mentioned?: globalThis.Record<string, unknown>;
}

export const CommentSchema = z.object({
  id: z.string(),
  text: z.string(),
  createdTime: z.string(),
  author: z.object({
    id: z.string(),
    email: z.string(),
    name: z.string().optional(),
  }),
  lastUpdatedTime: z.string().optional(),
  mentioned: z.record(z.unknown()).optional(),
});

// ============================================================================
// Pagination
// ============================================================================

export interface RecordsPagination {
  offset?: string;
}

export interface MetaPagination {
  cursor?: string;
}

export const RecordsPaginationSchema = z.object({
  offset: z.string().optional(),
});

export const MetaPaginationSchema = z.object({
  cursor: z.string().optional(),
});

// ============================================================================
// Filtering and Sorting
// ============================================================================

export type FilterFormula = string;

export interface SortConfig {
  field: string;
  direction: 'asc' | 'desc';
}

export const SortConfigSchema = z.object({
  field: z.string(),
  direction: z.enum(['asc', 'desc']),
});

// ============================================================================
// API Response Types
// ============================================================================

export interface ListBasesResponse {
  bases: Base[];
  offset?: string;
}

export interface ListTablesResponse {
  tables: Table[];
}

export interface ListRecordsResponse {
  records: AirtableRecord[];
  offset?: string;
}

export interface CreateRecordsResponse {
  records: AirtableRecord[];
  createdRecords?: AirtableRecord[];
}

export interface UpdateRecordsResponse {
  records: AirtableRecord[];
  updatedRecords?: AirtableRecord[];
}

export interface DeleteRecordsResponse {
  records: Array<{ id: RecordId; deleted: boolean }>;
}

export const ListBasesResponseSchema = z.object({
  bases: z.array(BaseSchema),
  offset: z.string().optional(),
});

export const ListTablesResponseSchema = z.object({
  tables: z.array(TableSchema),
});

export const ListRecordsResponseSchema = z.object({
  records: z.array(AirtableRecordSchema),
  offset: z.string().optional(),
});

export const CreateRecordsResponseSchema = z.object({
  records: z.array(AirtableRecordSchema),
  createdRecords: z.array(AirtableRecordSchema).optional(),
});

export const UpdateRecordsResponseSchema = z.object({
  records: z.array(AirtableRecordSchema),
  updatedRecords: z.array(AirtableRecordSchema).optional(),
});

export const DeleteRecordsResponseSchema = z.object({
  records: z.array(
    z.object({
      id: RecordIdSchema,
      deleted: z.boolean(),
    })
  ),
});
