/**
 * Shared API types for Redirect Intelligence v2
 */

import { z } from 'zod';

// Base API response
export const ApiResponseSchema = z.object({
  success: z.boolean(),
  status: z.number(),
  data: z.any().optional(),
  error: z.string().optional(),
  message: z.string().optional(),
  meta: z.record(z.any()).optional(),
});

export type ApiResponse<T = any> = {
  success: boolean;
  status: number;
  data?: T;
  error?: string;
  message?: string;
  meta?: Record<string, any>;
};

// Legacy redirect result (for backward compatibility)
export const LegacyRedirectSchema = z.object({
  url: z.string(),
  timestamp: z.number(),
  isSSL: z.boolean(),
  duration: z.number().optional(),
  statusCode: z.number().optional(),
  statusText: z.string().optional(),
  metadata: z.any().optional(),
  responseBody: z.string().optional(),
  sslInfo: z.any().optional(),
  error: z.string().optional(),
  final: z.boolean().optional(),
});

export type LegacyRedirect = z.infer<typeof LegacyRedirectSchema>;

// Legacy track request (v1)
export const TrackRequestSchema = z.object({
  url: z.string().url(),
  method: z.enum(['GET', 'HEAD', 'POST']).default('GET'),
  userAgent: z.string().optional(),
});

export type TrackRequest = z.infer<typeof TrackRequestSchema>;

// Legacy track response (v1)
export const TrackResponseSchema = z.object({
  url: z.string(),
  method: z.string(),
  redirectCount: z.number(),
  finalUrl: z.string(),
  finalStatusCode: z.number().optional(),
  redirects: z.array(LegacyRedirectSchema),
});

export type TrackResponse = z.infer<typeof TrackResponseSchema>;

// ============================================================================
// V2 ENHANCED TYPES
// ============================================================================

// Enhanced track request (v2)
export const TrackRequestV2Schema = z.object({
  url: z.string().url(),
  method: z.enum(['GET', 'POST', 'HEAD']).default('GET'),
  userAgent: z.string().optional(),
  headers: z.record(z.string()).optional(),
  projectId: z.string().optional(),
  followJS: z.boolean().default(false),
  maxHops: z.number().min(1).max(20).default(10),
  timeout: z.number().min(1000).max(30000).default(15000),
});

export type TrackRequestV2 = z.infer<typeof TrackRequestV2Schema>;

// Hop result (v2)
export const HopResultSchema = z.object({
  hopIndex: z.number(),
  url: z.string(),
  scheme: z.string().optional(),
  statusCode: z.number().optional(),
  redirectType: z.enum(['HTTP_301', 'HTTP_302', 'HTTP_307', 'HTTP_308', 'META_REFRESH', 'JS', 'FINAL', 'OTHER']),
  latencyMs: z.number().optional(),
  contentType: z.string().optional(),
  reason: z.string().optional(),
  responseHeaders: z.record(z.string()),
});

export type HopResult = z.infer<typeof HopResultSchema>;

// Check result (v2)
export const CheckResultSchema = z.object({
  id: z.string(),
  inputUrl: z.string(),
  method: z.string(),
  status: z.enum(['OK', 'ERROR', 'TIMEOUT', 'LOOP']),
  finalUrl: z.string().optional(),
  totalTimeMs: z.number(),
  startedAt: z.date(),
  finishedAt: z.date(),
  hops: z.array(HopResultSchema),
  redirectCount: z.number(),
  loopDetected: z.boolean().optional(),
  error: z.string().optional(),
});

export type CheckResult = z.infer<typeof CheckResultSchema>;

// Enhanced track response (v2)
export const TrackResponseV2Schema = z.object({
  success: z.boolean(),
  status: z.number(),
  data: z.object({
    check: CheckResultSchema,
    url: z.string(),
    method: z.string(),
    redirectCount: z.number(),
    finalUrl: z.string().optional(),
    finalStatusCode: z.number().optional(),
  }),
  meta: z.object({
    version: z.literal('v2'),
    enhanced: z.boolean(),
    persisted: z.boolean(),
    checkId: z.string(),
  }),
});

export type TrackResponseV2 = z.infer<typeof TrackResponseV2Schema>;

// ============================================================================
// AUTHENTICATION TYPES
// ============================================================================

export const AuthUserSchema = z.object({
  id: z.string(),
  email: z.string().email(),
  name: z.string(),
  memberships: z.array(z.object({
    orgId: z.string(),
    role: z.string(),
    organization: z.object({
      name: z.string(),
      plan: z.string(),
    }),
  })),
});

export type AuthUser = z.infer<typeof AuthUserSchema>;

export const LoginRequestSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});

export type LoginRequest = z.infer<typeof LoginRequestSchema>;

export const RegisterRequestSchema = z.object({
  email: z.string().email(),
  name: z.string().min(2),
  password: z.string().min(8),
  organizationName: z.string().min(2).optional(),
});

export type RegisterRequest = z.infer<typeof RegisterRequestSchema>;

export const AuthResponseSchema = z.object({
  success: z.boolean(),
  status: z.number(),
  data: z.object({
    user: AuthUserSchema,
    token: z.string().optional(),
  }),
  message: z.string().optional(),
});

export type AuthResponse = z.infer<typeof AuthResponseSchema>;

// ============================================================================
// PROJECT & ORGANIZATION TYPES
// ============================================================================

export const ProjectSchema = z.object({
  id: z.string(),
  name: z.string(),
  orgId: z.string(),
  settingsJson: z.record(z.any()),
  createdAt: z.date(),
});

export type Project = z.infer<typeof ProjectSchema>;

export const OrganizationSchema = z.object({
  id: z.string(),
  name: z.string(),
  plan: z.string(),
  createdAt: z.date(),
});

export type Organization = z.infer<typeof OrganizationSchema>;

// ============================================================================
// UTILITY TYPES
// ============================================================================

export type CheckStatus = 'OK' | 'ERROR' | 'TIMEOUT' | 'LOOP';
export type RedirectType = 'HTTP_301' | 'HTTP_302' | 'HTTP_307' | 'HTTP_308' | 'META_REFRESH' | 'JS' | 'FINAL' | 'OTHER';
export type UserRole = 'OWNER' | 'ADMIN' | 'MEMBER';

// Error response
export const ErrorResponseSchema = z.object({
  success: z.literal(false),
  error: z.string(),
  message: z.string(),
  status: z.number(),
  details: z.any().optional(),
});

export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;