import {
  SiteSettings,
  GolfServicesPageData,
  Post,
  Page,
  Media,
  User,
  PaginatedResponse,
  AuthResponse,
  Service,
  AboutPageData,
  GolfAcademyData,
  CoachInquiry,
  BookLessonData,
  LessonBooking,
  GroupServicesData,
  GolfDevelopmentFundData,
  EventGalleryItem,
  EventGallerySettingsData,
  GolfIdData,
  MembershipOffersData,
  UpgradeOffersData,
  MemberRewardsData,
  BonusPointsData,
  HomePageData,
  PartnersData,
  ContactPageData,
  ContactInquiryData,
  PrivacyPageData,
  EshopData,
  EventsPageData,
  SidebarContentItem,
  Package,
} from '@/types';

const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api';

class ApiClient {
  private baseUrl: string;
  private token: string | null = null;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  setToken(token: string | null) {
    this.token = token;
    if (typeof window !== 'undefined') {
      if (token) {
        localStorage.setItem('admin_token', token);
      } else {
        localStorage.removeItem('admin_token');
      }
    }
  }

  getToken(): string | null {
    if (this.token) return this.token;
    if (typeof window !== 'undefined') {
      return localStorage.getItem('admin_token');
    }
    return null;
  }

  private async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`;
    const headers: Record<string, string> = {};

    if (!(options.body instanceof FormData)) {
      headers['Content-Type'] = 'application/json';
    }

    if (options.headers) {
      Object.assign(headers, options.headers);
    }

    const token = this.getToken();
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }

    const response = await fetch(url, {
      ...options,
      headers,
    });

    if (response.status === 401) {
      this.setToken(null);
      if (typeof window !== 'undefined') {
        const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';
        window.location.href = `${basePath}/login`;
      }
      throw new Error('Unauthorized');
    }

    if (!response.ok) {
      const error = await response.json().catch(() => ({ error: 'An error occurred' }));
      throw new Error(error.error || error.message || 'An error occurred');
    }

    return response.json();
  }

  // ---- AUTH ----
  async login(email: string, password: string): Promise<AuthResponse> {
    const response = await this.request<AuthResponse>('/auth/login', {
      method: 'POST',
      body: JSON.stringify({ email, password }),
    });
    this.setToken(response.token);
    return response;
  }

  logout() {
    this.setToken(null);
  }

  async getCurrentUser(): Promise<{ user: User }> {
    return this.request<{ user: User }>('/auth/me');
  }

  async changePassword(currentPassword: string, newPassword: string): Promise<void> {
    return this.request('/auth/password', {
      method: 'PUT',
      body: JSON.stringify({ currentPassword, newPassword }),
    });
  }

  // ---- POSTS ----
  async getAdminPosts(params?: {
    status?: string;
    page?: number;
    limit?: number;
    sort?: string;
  }): Promise<PaginatedResponse<Post>> {
    const searchParams = new URLSearchParams();
    if (params?.status) searchParams.set('status', params.status);
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    if (params?.sort) searchParams.set('sort', params.sort);
    const query = searchParams.toString();
    return this.request<PaginatedResponse<Post>>(`/posts/admin${query ? `?${query}` : ''}`);
  }

  async getPost(id: string): Promise<Post> {
    return this.request<Post>(`/posts/admin/${id}`);
  }

  async createPost(data: Partial<Post>): Promise<Post> {
    return this.request<Post>('/posts', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updatePost(id: string, data: Partial<Post>): Promise<Post> {
    return this.request<Post>(`/posts/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deletePost(id: string): Promise<void> {
    return this.request(`/posts/${id}`, { method: 'DELETE' });
  }

  async getCategories(): Promise<string[]> {
    return this.request<string[]>('/posts/categories/all');
  }

  async renameCategory(oldName: string, newName: string): Promise<{ updated: number }> {
    return this.request<{ updated: number }>(`/posts/categories/${encodeURIComponent(oldName)}`, {
      method: 'PUT',
      body: JSON.stringify({ newName }),
    });
  }

  async deleteCategory(name: string, fallback = 'General'): Promise<{ updated: number }> {
    return this.request<{ updated: number }>(
      `/posts/categories/${encodeURIComponent(name)}?fallback=${encodeURIComponent(fallback)}`,
      { method: 'DELETE' }
    );
  }

  // ---- PAGES ----
  async getAdminPages(params?: {
    status?: string;
    page?: number;
    limit?: number;
  }): Promise<PaginatedResponse<Page>> {
    const searchParams = new URLSearchParams();
    if (params?.status) searchParams.set('status', params.status);
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request<PaginatedResponse<Page>>(`/pages/admin${query ? `?${query}` : ''}`);
  }

  async getPage(id: string): Promise<Page> {
    return this.request<Page>(`/pages/admin/${id}`);
  }

  async createPage(data: Partial<Page>): Promise<Page> {
    return this.request<Page>('/pages', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updatePage(id: string, data: Partial<Page>): Promise<Page> {
    return this.request<Page>(`/pages/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deletePage(id: string): Promise<void> {
    return this.request(`/pages/${id}`, { method: 'DELETE' });
  }

  // ---- GOLF SERVICES PAGE ----
  async getGolfServicesPage(): Promise<GolfServicesPageData> {
    return this.request<GolfServicesPageData>('/golf-services-page');
  }

  async updateGolfServicesPage(data: Partial<GolfServicesPageData>): Promise<GolfServicesPageData> {
    return this.request<GolfServicesPageData>('/golf-services-page', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- SERVICES ----
  async getServices(): Promise<Service[]> {
    return this.request<Service[]>('/services/admin');
  }

  async getService(id: string): Promise<Service> {
    return this.request<Service>(`/services/admin/${id}`);
  }

  async createService(data: Partial<Service>): Promise<Service> {
    return this.request<Service>('/services', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updateService(id: string, data: Partial<Service>): Promise<Service> {
    return this.request<Service>(`/services/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteService(id: string): Promise<void> {
    return this.request(`/services/${id}`, { method: 'DELETE' });
  }

  async reorderServices(order: string[]): Promise<void> {
    return this.request('/services/reorder', {
      method: 'PUT',
      body: JSON.stringify({ order }),
    });
  }

  // ---- MEDIA ----
  async getMedia(params?: {
    folder?: string;
    type?: string;
    page?: number;
    limit?: number;
  }): Promise<PaginatedResponse<Media>> {
    const searchParams = new URLSearchParams();
    if (params?.folder) searchParams.set('folder', params.folder);
    if (params?.type) searchParams.set('type', params.type);
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request<PaginatedResponse<Media>>(`/media${query ? `?${query}` : ''}`);
  }

  async uploadMedia(formData: FormData): Promise<Media> {
    return this.request<Media>('/media', {
      method: 'POST',
      body: formData,
    });
  }

  async updateMedia(id: string, data: { alt?: string; caption?: string; folder?: string }): Promise<Media> {
    return this.request<Media>(`/media/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteMedia(id: string): Promise<void> {
    return this.request(`/media/${id}`, { method: 'DELETE' });
  }

  // ---- USERS ----
  async getUsers(params?: {
    role?: string;
    page?: number;
    limit?: number;
  }): Promise<PaginatedResponse<User>> {
    const searchParams = new URLSearchParams();
    if (params?.role) searchParams.set('role', params.role);
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request<PaginatedResponse<User>>(`/users${query ? `?${query}` : ''}`);
  }

  async getUserById(id: string): Promise<User> {
    return this.request<User>(`/users/${id}`);
  }

  async createUser(data: {
    email: string;
    password: string;
    name: string;
    role: string;
  }): Promise<User> {
    return this.request<User>('/users', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updateUser(id: string, data: Partial<User> & { password?: string }): Promise<User> {
    return this.request<User>(`/users/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteUser(id: string): Promise<void> {
    return this.request(`/users/${id}`, { method: 'DELETE' });
  }

  // ---- SETTINGS ----
  async getSettings(): Promise<SiteSettings> {
    return this.request<SiteSettings>('/settings');
  }

  async updateSettings(data: Partial<SiteSettings>): Promise<SiteSettings> {
    return this.request<SiteSettings>('/settings', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- ABOUT PAGE ----
  async getAboutPage(): Promise<AboutPageData> {
    return this.request<AboutPageData>('/about');
  }

  async updateAboutPage(data: Partial<AboutPageData>): Promise<AboutPageData> {
    return this.request<AboutPageData>('/about', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- GOLF ACADEMY ----
  async getGolfAcademy(): Promise<GolfAcademyData> {
    return this.request<GolfAcademyData>('/golf-academy');
  }

  async updateGolfAcademy(data: Partial<GolfAcademyData>): Promise<GolfAcademyData> {
    return this.request<GolfAcademyData>('/golf-academy', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async getCoachInquiries(params?: {
    page?: number;
    limit?: number;
  }): Promise<{ inquiries: CoachInquiry[]; pagination: PaginatedResponse<never>['pagination'] }> {
    const searchParams = new URLSearchParams();
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request(`/golf-academy/inquiries${query ? `?${query}` : ''}`);
  }

  // ---- BOOK LESSONS ----
  async getBookLesson(): Promise<BookLessonData> {
    return this.request<BookLessonData>('/book-lessons');
  }

  async updateBookLesson(data: Partial<BookLessonData>): Promise<BookLessonData> {
    return this.request<BookLessonData>('/book-lessons', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async getBookLessonBookings(params?: {
    page?: number;
    limit?: number;
    status?: string;
  }): Promise<{ bookings: LessonBooking[]; pagination: PaginatedResponse<never>['pagination'] }> {
    const searchParams = new URLSearchParams();
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    if (params?.status) searchParams.set('status', params.status);
    const query = searchParams.toString();
    return this.request(`/book-lessons/bookings${query ? `?${query}` : ''}`);
  }

  async updateBookingStatus(id: string, data: { status?: string; notes?: string }): Promise<LessonBooking> {
    return this.request<LessonBooking>(`/book-lessons/bookings/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- GROUP SERVICES ----
  async getGroupServices(): Promise<GroupServicesData> {
    return this.request<GroupServicesData>('/group-services');
  }

  async updateGroupServices(data: Partial<GroupServicesData>): Promise<GroupServicesData> {
    return this.request<GroupServicesData>('/group-services', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async getEventsPage(): Promise<EventsPageData> {
    return this.request<EventsPageData>('/events-page');
  }

  async updateEventsPage(data: Partial<EventsPageData>): Promise<EventsPageData> {
    return this.request<EventsPageData>('/events-page', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- GOLF DEVELOPMENT FUND ----
  async getGDF(): Promise<GolfDevelopmentFundData> {
    return this.request<GolfDevelopmentFundData>('/gdf');
  }

  async updateGDF(data: Partial<GolfDevelopmentFundData>): Promise<GolfDevelopmentFundData> {
    return this.request<GolfDevelopmentFundData>('/gdf', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- EVENT GALLERY ----
  async getEventGallerySettings(): Promise<EventGallerySettingsData> {
    return this.request<EventGallerySettingsData>('/event-gallery/settings');
  }

  async updateEventGallerySettings(data: Partial<EventGallerySettingsData>): Promise<EventGallerySettingsData> {
    return this.request<EventGallerySettingsData>('/event-gallery/settings', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async getAdminEventGallery(params?: {
    page?: number;
    limit?: number;
  }): Promise<{ events: EventGalleryItem[]; pagination: PaginatedResponse<never>['pagination'] }> {
    const searchParams = new URLSearchParams();
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request(`/event-gallery/admin/all${query ? `?${query}` : ''}`);
  }

  async getEventGalleryItem(id: string): Promise<EventGalleryItem> {
    return this.request<EventGalleryItem>(`/event-gallery/admin/${id}`);
  }

  async createEventGalleryItem(data: Partial<EventGalleryItem>): Promise<EventGalleryItem> {
    return this.request<EventGalleryItem>('/event-gallery', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updateEventGalleryItem(id: string, data: Partial<EventGalleryItem>): Promise<EventGalleryItem> {
    return this.request<EventGalleryItem>(`/event-gallery/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteEventGalleryItem(id: string): Promise<void> {
    return this.request(`/event-gallery/${id}`, { method: 'DELETE' });
  }

  async batchUpdateEventGallery(
    updates: Array<{ id: string; order?: number; cardSize?: string }>
  ): Promise<{ modifiedCount: number }> {
    return this.request('/event-gallery/batch', {
      method: 'PUT',
      body: JSON.stringify({ updates }),
    });
  }

  // ---- GOLF ID ----
  async getGolfId(): Promise<GolfIdData> {
    return this.request<GolfIdData>('/golf-id');
  }

  async updateGolfId(data: Partial<GolfIdData>): Promise<GolfIdData> {
    return this.request<GolfIdData>('/golf-id', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- MEMBERSHIP OFFERS ----
  async getMembershipOffers(): Promise<MembershipOffersData> {
    return this.request<MembershipOffersData>('/membership-offers');
  }

  async updateMembershipOffers(data: Partial<MembershipOffersData>): Promise<MembershipOffersData> {
    return this.request<MembershipOffersData>('/membership-offers', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- UPGRADE OFFERS ----
  async getUpgradeOffers(): Promise<UpgradeOffersData> {
    return this.request<UpgradeOffersData>('/upgrade-offers');
  }

  async updateUpgradeOffers(data: Partial<UpgradeOffersData>): Promise<UpgradeOffersData> {
    return this.request<UpgradeOffersData>('/upgrade-offers', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- MEMBER REWARDS ----
  async getMemberRewards(): Promise<MemberRewardsData> {
    return this.request<MemberRewardsData>('/member-rewards');
  }

  async updateMemberRewards(data: Partial<MemberRewardsData>): Promise<MemberRewardsData> {
    return this.request<MemberRewardsData>('/member-rewards', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- BONUS POINTS ----
  async getBonusPoints(): Promise<BonusPointsData> {
    return this.request<BonusPointsData>('/bonus-points');
  }

  async updateBonusPoints(data: Partial<BonusPointsData>): Promise<BonusPointsData> {
    return this.request<BonusPointsData>('/bonus-points', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  // ---- HOMEPAGE ----
  async getHomePage(): Promise<HomePageData> {
    return this.request<HomePageData>('/homepage');
  }

  async updateHomePage(data: Partial<HomePageData>): Promise<HomePageData> {
    return this.request<HomePageData>('/homepage', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- PARTNERS ----
  async getPartners(): Promise<PartnersData> {
    return this.request<PartnersData>('/partners');
  }

  async updatePartners(data: Partial<PartnersData>): Promise<PartnersData> {
    return this.request<PartnersData>('/partners', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- CONTACT PAGE ----
  async getContactPage(): Promise<ContactPageData> {
    return this.request<ContactPageData>('/contact');
  }

  async updateContactPage(data: Partial<ContactPageData>): Promise<ContactPageData> {
    return this.request<ContactPageData>('/contact', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async getContactInquiries(params?: {
    page?: number;
    limit?: number;
  }): Promise<{ inquiries: ContactInquiryData[]; pagination: PaginatedResponse<never>['pagination'] }> {
    const searchParams = new URLSearchParams();
    if (params?.page) searchParams.set('page', params.page.toString());
    if (params?.limit) searchParams.set('limit', params.limit.toString());
    const query = searchParams.toString();
    return this.request(`/contact/inquiries${query ? `?${query}` : ''}`);
  }
  // ---- PRIVACY PAGE ----
  async getPrivacyPage(): Promise<PrivacyPageData> {
    return this.request<PrivacyPageData>('/privacy');
  }

  async updatePrivacyPage(data: Partial<PrivacyPageData>): Promise<PrivacyPageData> {
    return this.request<PrivacyPageData>('/privacy', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- ESHOP ----
  async getEshop(): Promise<EshopData> {
    return this.request<EshopData>('/eshop');
  }

  async updateEshop(data: Partial<EshopData>): Promise<EshopData> {
    return this.request<EshopData>('/eshop', {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }
  // ---- SIDEBAR CONTENT ----
  async getSidebarContent(): Promise<SidebarContentItem[]> {
    return this.request<SidebarContentItem[]>('/sidebar-content/admin');
  }

  async createSidebarContent(data: Partial<SidebarContentItem>): Promise<SidebarContentItem> {
    return this.request<SidebarContentItem>('/sidebar-content', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updateSidebarContent(id: string, data: Partial<SidebarContentItem>): Promise<SidebarContentItem> {
    return this.request<SidebarContentItem>(`/sidebar-content/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteSidebarContent(id: string): Promise<void> {
    return this.request(`/sidebar-content/${id}`, { method: 'DELETE' });
  }

  // ---- PACKAGES ----
  async getPackages(): Promise<Package[]> {
    return this.request<Package[]>('/packages/admin');
  }

  async createPackage(data: Partial<Package>): Promise<Package> {
    return this.request<Package>('/packages', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updatePackage(id: string, data: Partial<Package>): Promise<Package> {
    return this.request<Package>(`/packages/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deletePackage(id: string): Promise<void> {
    return this.request(`/packages/${id}`, { method: 'DELETE' });
  }
}

export const api = new ApiClient(API_URL);
export default api;
