import type { ApiResponse, components } from '@alqove/types';
import type { AlqoveClient } from '../client';

export type StorefrontShell = components['schemas']['StorefrontShell'];
export type StorefrontPage = components['schemas']['StorefrontPage'];
export type StorefrontResolution = components['schemas']['StorefrontResolution'];
export type StoreSite = components['schemas']['StoreSite'];
export type StoreSitePage = components['schemas']['StoreSitePage'];
export type StoreSiteBlock = components['schemas']['StoreSiteBlock'];
export type StoreSiteTheme = components['schemas']['StoreSiteTheme'];
export type StoreSiteHoursEntry = components['schemas']['StoreSiteHoursEntry'];
export type StoreSiteSocialLink = components['schemas']['StoreSiteSocialLink'];
export type StoreDomain = components['schemas']['StoreDomain'];
export type StorefrontNavLink = components['schemas']['StorefrontNavLink'];

export type UpdateStoreSitePayload = components['schemas']['UpdateStoreSiteRequest'];
export type CreateStoreSitePagePayload = components['schemas']['CreateStoreSitePageRequest'];
export type UpdateStoreSitePagePayload = components['schemas']['UpdateStoreSitePageRequest'];

/** The `data` shape of a block, narrowed per type at the render site. */
export type StoreSiteBlockType = NonNullable<StoreSiteBlock['type']>;

/** A page fetch also carries the shell, so one request paints the whole screen. */
export interface StorefrontPageResponse {
  data: StorefrontPage;
  meta: { storefront: StorefrontShell };
}

export function createStorefrontEndpoints(client: AlqoveClient) {
  return {
    // ---- Public ------------------------------------------------------------

    /** Host header → store slug. Used by the web tier's custom-domain middleware. */
    resolveDomain(hostname: string) {
      return client.get<ApiResponse<StorefrontResolution>>('/v1/storefronts/resolve', {
        hostname,
      });
    },

    getShell(slug: string) {
      return client.get<ApiResponse<StorefrontShell>>(
        `/v1/storefronts/${encodeURIComponent(slug)}`,
      );
    },

    getPage(slug: string, pageSlug: string) {
      return client.get<StorefrontPageResponse>(
        `/v1/storefronts/${encodeURIComponent(slug)}/pages/${encodeURIComponent(pageSlug)}`,
      );
    },

    // ---- Seller editor -----------------------------------------------------

    getSite(storeId: string) {
      return client.get<ApiResponse<StoreSite>>(`/v1/stores/${storeId}/site`);
    },

    updateSite(storeId: string, payload: UpdateStoreSitePayload) {
      return client.put<ApiResponse<StoreSite>>(`/v1/stores/${storeId}/site`, payload);
    },

    updateSlug(storeId: string, slug: string) {
      return client.put<ApiResponse<StoreSite>>(`/v1/stores/${storeId}/site/slug`, { slug });
    },

    pages: {
      list(storeId: string) {
        return client.get<ApiResponse<StoreSitePage[]>>(`/v1/stores/${storeId}/site/pages`);
      },
      create(storeId: string, payload: CreateStoreSitePagePayload) {
        return client.post<ApiResponse<StoreSitePage>>(
          `/v1/stores/${storeId}/site/pages`,
          payload,
        );
      },
      update(storeId: string, pageId: string, payload: UpdateStoreSitePagePayload) {
        return client.put<ApiResponse<StoreSitePage>>(
          `/v1/stores/${storeId}/site/pages/${pageId}`,
          payload,
        );
      },
      remove(storeId: string, pageId: string) {
        return client.delete<{ message: string }>(
          `/v1/stores/${storeId}/site/pages/${pageId}`,
        );
      },
      /** Send every page id exactly once — index becomes position. */
      reorder(storeId: string, pageIds: string[]) {
        return client.put<ApiResponse<StoreSitePage[]>>(
          `/v1/stores/${storeId}/site/pages/reorder`,
          { page_ids: pageIds },
        );
      },
    },

    domains: {
      list(storeId: string) {
        return client.get<ApiResponse<StoreDomain[]>>(`/v1/stores/${storeId}/domains`);
      },
      create(storeId: string, hostname: string) {
        return client.post<ApiResponse<StoreDomain>>(`/v1/stores/${storeId}/domains`, {
          hostname,
        });
      },
      /** Returns 422 with the refreshed domain when DNS still doesn't match. */
      verify(storeId: string, domainId: string) {
        return client.post<ApiResponse<StoreDomain> & { meta?: { verified: boolean } }>(
          `/v1/stores/${storeId}/domains/${domainId}/verify`,
          {},
        );
      },
      makePrimary(storeId: string, domainId: string) {
        return client.put<ApiResponse<StoreDomain>>(
          `/v1/stores/${storeId}/domains/${domainId}/primary`,
          {},
        );
      },
      remove(storeId: string, domainId: string) {
        return client.delete<{ message: string }>(
          `/v1/stores/${storeId}/domains/${domainId}`,
        );
      },
    },
  };
}
