import {
  User as SharedUser,
  Client,
  FitnessProfile,
  Attendance,
  Recommendation,
  FitnessGoal,
  Notification,
} from "@fitai/shared";
import type { SortConfig, FilterCondition } from "../filtering";

// Database Entity Types
export interface User extends SharedUser {
  // Explicitly include gymId so server imports can rely on it even if shared types lag behind build
  gymId?: string;
  password: string;
}

export type {
  Client,
  FitnessProfile,
  Attendance,
  Recommendation,
  FitnessGoal,
  Notification,
};

// Database Interface - allows us to swap implementations
export interface IDatabase {
  // Connection management
  connect(): Promise<void>;
  disconnect(): Promise<void>;

  // User operations
  createUser(
    user: Omit<User, "createdAt" | "updatedAt" | "id"> & { id?: string },
  ): Promise<User>;
  getUserById(id: string): Promise<User | null>;
  getUserByEmail(email: string): Promise<User | null>;
  getAllUsers(): Promise<User[]>;
  updateUser(id: string, updates: Partial<User>): Promise<User | null>;
  deleteUser(id: string): Promise<boolean>;
  migrateUserId(oldId: string, newId: string): Promise<void>;

  // Optimized query methods (Phase 3 & 4 additions)
  getUsersWithPagination(params: {
    page: number;
    limit: number;
    role?: string;
    sort?: SortConfig;
    filters?: FilterCondition[];
    search?: string;
  }): Promise<{ users: User[]; total: number }>;

  getUsersWithRelatedData(params?: {
    page?: number;
    limit?: number;
    role?: string;
    sort?: SortConfig;
    filters?: FilterCondition[];
    search?: string;
  }): Promise<{
    users: Array<
      User & {
        client?: Client | null;
        isCheckedIn?: boolean;
        checkInTime?: Date | null;
        lastCheckInTime?: Date | null;
        checkInsThisWeek?: number;
        checkInsThisMonth?: number;
      }
    >;
    total?: number;
  }>;

  getAttendanceStatsBatch(userIds: string[]): Promise<
    Map<
      string,
      {
        isCheckedIn: boolean;
        checkInTime: Date | null;
        lastCheckInTime: Date | null;
        checkInsThisWeek: number;
        checkInsThisMonth: number;
      }
    >
  >;

  // Client operations
  createClient(client: Omit<Client, "id">): Promise<Client>;
  getClientById(id: string): Promise<Client | null>;
  getClientByUserId(userId: string): Promise<Client | null>;
  getClientsByUserIds(userIds: string[]): Promise<Client[]>;
  getAllClients(): Promise<Client[]>;
  getClientsWithPagination(params: {
    page: number;
    limit: number;
    sort?: SortConfig;
    filters?: FilterCondition[];
    search?: string;
  }): Promise<{ clients: Client[]; total: number }>;
  updateClient(id: string, updates: Partial<Client>): Promise<Client | null>;
  deleteClient(id: string): Promise<boolean>;

  // Fitness Profile operations
  createFitnessProfile(
    profile: Omit<FitnessProfile, "createdAt" | "updatedAt">,
  ): Promise<FitnessProfile>;
  getFitnessProfileByUserId(userId: string): Promise<FitnessProfile | null>;
  getAllFitnessProfiles(): Promise<FitnessProfile[]>;
  updateFitnessProfile(
    userId: string,
    updates: Partial<FitnessProfile>,
  ): Promise<FitnessProfile | null>;
  deleteFitnessProfile(userId: string): Promise<boolean>;

  // Attendance operations
  checkIn(
    userId: string,
    type: "gym" | "class" | "personal_training",
    notes?: string,
  ): Promise<Attendance>;
  checkOut(attendanceId: string): Promise<Attendance | null>;
  getAttendanceHistory(userId: string): Promise<Attendance[]>;
  getAttendanceHistoriesByUserIds(userIds: string[]): Promise<Attendance[]>;
  getActiveCheckInsByUserIds(userIds: string[]): Promise<Attendance[]>;
  getAllAttendance(): Promise<Attendance[]>;
  getAttendanceWithPagination(params: {
    page: number;
    limit: number;
    sort?: SortConfig;
    filters?: FilterCondition[];
    search?: string;
  }): Promise<{ attendance: Attendance[]; total: number }>;
  getActiveCheckIn(userId: string): Promise<Attendance | null>;

  // Recommendation operations
  createRecommendation(
    recommendation: Omit<
      Recommendation,
      "createdAt" | "approvedAt" | "approvedBy"
    >,
  ): Promise<Recommendation>;
  getRecommendationsByUserId(userId: string): Promise<Recommendation[]>;
  getRecommendationsByUserIds(userIds: string[]): Promise<Recommendation[]>;
  getAllRecommendations(): Promise<Recommendation[]>;
  updateRecommendation(
    id: string,
    updates: Partial<Recommendation>,
  ): Promise<Recommendation | null>;
  deleteRecommendation(id: string): Promise<boolean>;

  // Fitness Goals operations
  createFitnessGoal(
    goal: Omit<FitnessGoal, "createdAt" | "updatedAt">,
  ): Promise<FitnessGoal>;
  getFitnessGoalById(id: string): Promise<FitnessGoal | null>;
  getFitnessGoalsByUserId(
    userId: string,
    status?: string,
  ): Promise<FitnessGoal[]>;
  getFitnessGoalsByUserIds(userIds: string[]): Promise<FitnessGoal[]>;
  updateFitnessGoal(
    id: string,
    updates: Partial<FitnessGoal>,
  ): Promise<FitnessGoal | null>;
  deleteFitnessGoal(id: string): Promise<boolean>;
  updateGoalProgress(
    id: string,
    currentValue: number,
  ): Promise<FitnessGoal | null>;
  completeGoal(id: string): Promise<FitnessGoal | null>;

  // Notification operations
  createNotification(
    notification: Omit<Notification, "createdAt">,
  ): Promise<Notification>;
  getNotificationsByUserId(userId: string): Promise<Notification[]>;
  getUnreadNotificationCount(userId: string): Promise<number>;
  markNotificationAsRead(id: string): Promise<Notification | null>;
  markAllNotificationsAsRead(userId: string): Promise<void>;
  deleteNotification(id: string): Promise<boolean>;

  // Dashboard operations
  getDashboardStats(): Promise<{
    totalUsers: number;
    activeClients: number;
    totalRevenue: number;
    revenueGrowth: number; // Percentage vs last month
  }>;
}

// Database configuration
export interface DatabaseConfig {
  type: "sqlite" | "postgresql" | "mysql" | "mongodb";
  connection: {
    filename?: string; // for SQLite
    host?: string; // for SQL databases
    port?: number;
    database?: string;
    username?: string;
    password?: string;
  };
  options?: {
    logging?: boolean;
    poolSize?: number;
    timeout?: number;
  };
}
