import {
  Product,
  Gender,
  UserState,
  MinisContentStatus,
} from '@shopify/shop-minis-platform'
import {ShopActions} from '@shopify/shop-minis-platform/actions'

// Helper functions for common data structures
export const createProduct = (
  id: string,
  title: string,
  price = '99.99',
  compareAtPrice?: string
): Product => ({
  id,
  title,
  price: {amount: price, currencyCode: 'USD'},
  ...(compareAtPrice && {
    compareAtPrice: {amount: compareAtPrice, currencyCode: 'USD'},
  }),
  reviewAnalytics: {averageRating: 4.5, reviewCount: 10},
  shop: createShop('shop1', 'Mock Shop'),
  defaultVariantId: `variant-${id}`,
  isFavorited: false,
  featuredImage: {
    url: `https://cdn.shopify.com/static/sample-images/teapot.jpg`,
    altText: title,
  },
})

export const createShop = (
  id: string,
  name: string,
  options?: {
    themeType?: 'coverImage' | 'brandColor' | 'logoColor' | 'none'
    withBrandSettings?: boolean
    primaryColor?: string
    logoDominantColor?: string
    logoAverageColor?: string
    coverDominantColor?: string
    wordmarkUrl?: string
    coverImageUrl?: string
    featuredImagesLimit?: number
  }
) => {
  // Determine theme configuration
  const themeType = options?.themeType || 'none'
  const shouldHaveBrandSettings =
    options?.withBrandSettings || themeType !== 'none'

  // Generate featured images
  const featuredImagesCount = options?.featuredImagesLimit || 3
  const featuredImages = Array.from({length: featuredImagesCount}, (_, i) => ({
    url: `https://picsum.photos/400/400?random=${id}-${i}`,
    sensitive: false,
    altText: `${name} featured image ${i + 1}`,
  }))

  // Configure colors based on theme type
  const getThemeColors = () => {
    switch (themeType) {
      case 'coverImage':
        return {
          primary: options?.primaryColor,
          logoDominant: options?.logoDominantColor,
          logoAverage: options?.logoAverageColor,
          coverDominant: options?.coverDominantColor || '#FF6B35',
        }
      case 'brandColor':
        return {
          primary: options?.primaryColor || '#27AE60',
          logoDominant: options?.logoDominantColor,
          logoAverage: options?.logoAverageColor,
          coverDominant: options?.coverDominantColor,
        }
      case 'logoColor':
        return {
          primary: options?.primaryColor,
          logoDominant: options?.logoDominantColor || '#E74C3C',
          logoAverage: options?.logoAverageColor,
          coverDominant: options?.coverDominantColor,
        }
      default:
        return {
          primary: options?.primaryColor,
          logoDominant: options?.logoDominantColor,
          logoAverage: options?.logoAverageColor,
          coverDominant: options?.coverDominantColor,
        }
    }
  }

  // Configure header theme
  const createHeaderTheme = () => {
    if (themeType === 'coverImage' || options?.coverImageUrl) {
      return {
        id: `header-theme-${id}`,
        coverImage: {
          url:
            options?.coverImageUrl ||
            'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=800&h=400&fit=crop',
          altText: `${name} cover image`,
          sensitive: false,
          thumbhash: 'k9oGHQRnh493V4dIeHeXh4h3iIeI',
        },
        wordmark:
          options?.wordmarkUrl || themeType === 'coverImage'
            ? {
                url:
                  options?.wordmarkUrl ||
                  'https://merrypeople.com/cdn/shop/files/Transparent_Background_1.png?v=1696465429&width=1024',
                altText: `${name} wordmark`,
                sensitive: false,
              }
            : undefined,
      }
    }

    if (options?.wordmarkUrl) {
      return {
        id: `header-theme-${id}`,
        wordmark: {
          url: options.wordmarkUrl,
          altText: `${name} wordmark`,
          sensitive: false,
        },
      }
    }

    return undefined
  }

  return {
    id,
    name,
    primaryDomain: {
      url: `https://${name.toLowerCase().replace(/\s+/g, '-')}.com`,
    },
    reviewAnalytics: {averageRating: 4.3, reviewCount: 50},
    visualTheme: {
      id: `visual-theme-${id}`,
      featuredImages,
      logoImage: {
        url: `https://picsum.photos/100/100?random=${id}`,
        sensitive: false,
      },
      brandSettings: shouldHaveBrandSettings
        ? {
            id: `brand-settings-${id}`,
            colors: {
              id: `colors-${id}`,
              ...getThemeColors(),
            },
            headerTheme: createHeaderTheme(),
          }
        : undefined,
    },
  }
}

const createPagination = (hasNext = false) => ({
  hasNextPage: hasNext,
  endCursor: hasNext ? 'cursor123' : null,
})

const createProductList = (id: string, name: string, products: any[] = []) => ({
  id,
  publicId: `public-${id}`,
  name,
  products,
})

// Helper type to extract the data type from a ShopAction
type ShopActionDataType<T> = T extends (
  ...args: any[]
) => Promise<{ok: true; data: infer R} | {ok: false; error: any}>
  ? R
  : never

function makeMockMethod<K extends keyof ShopActions>(
  key: K,
  result: ShopActionDataType<ShopActions[K]>
): ShopActions[K] {
  return ((params: Parameters<ShopActions[K]>[0]) => {
    console.log(`[Mock Action] ${String(key)}`, params)
    return Promise.resolve({ok: true as const, data: result})
  }) as ShopActions[K]
}

export function makeMockActions(): ShopActions {
  const results: {
    [K in keyof ShopActions]: ShopActionDataType<ShopActions[K]>
  } = {
    translateContentUp: undefined,
    translateContentDown: undefined,
    followShop: true,
    unfollowShop: false,
    favorite: undefined,
    unfavorite: undefined,
    getShopAppInformation: {
      appVersion: '1.0.0',
      buildNumber: '12345',
      buildId: 'dev-build-123',
    },
    productRecommendationImpression: undefined,
    productRecommendationClick: undefined,
    hideEntryPoint: undefined,
    closeMini: undefined,
    getAccountInformation: {
      status: 'available',
      value: 'user@example.com',
    },
    getCurrentUser: {
      data: {
        displayName: 'John Doe',
        avatarImage: {url: 'https://example.com/avatar.jpg'},
      },
    },
    createOrderAttribution: undefined,
    addToCart: undefined,
    buyProduct: undefined,
    buyProducts: undefined,
    showErrorScreen: undefined,
    showErrorToast: undefined,
    getDeeplinkPaths: {
      matchers: ['/products', '/collections', '/cart'],
    },
    navigateToDeeplink: undefined,
    navigateToShop: undefined,
    navigateToProduct: undefined,
    navigateToOrder: undefined,
    navigateToCheckout: undefined,
    createImageUploadLink: {
      targets: [
        {
          url: 'https://example.com/upload',
          resourceUrl: 'https://example.com/resource',
          parameters: [{name: 'key', value: 'upload-123'}],
        },
      ],
    },
    completeImageUpload: {
      files: [
        {
          id: 'file-123',
          fileStatus: 'READY',
          image: {url: 'https://example.com/image.jpg'},
        },
      ],
    },
    getPersistedItem: null,
    setPersistedItem: undefined,
    removePersistedItem: undefined,
    getAllPersistedKeys: ['key1', 'key2', 'key3'],
    clearPersistedItems: undefined,
    getInternalPersistedItem: null,
    setInternalPersistedItem: undefined,
    removeInternalPersistedItem: undefined,
    getAllInternalPersistedKeys: ['internal-key1', 'internal-key2'],
    clearInternalPersistedItems: undefined,
    getSecret: 'secret-value',
    setSecret: undefined,
    removeSecret: undefined,
    reportInteraction: undefined,
    reportImpression: undefined,
    reportContentImpression: undefined,
    getProductLists: {
      data: [
        createProductList('list-1', 'Wishlist'),
        createProductList('list-2', 'Favorites'),
      ],
      pageInfo: createPagination(),
    },
    getProductList: {
      data: createProductList('list-1', 'Wishlist', [
        createProduct('prod-1', 'Sample Product'),
      ]),
      pageInfo: createPagination(),
    },
    addProductList: createProductList('list-3', 'New List'),
    removeProductList: undefined,
    renameProductList: createProductList('list-1', 'Updated Wishlist'),
    addProductListItem: undefined,
    removeProductListItem: undefined,
    getRecommendedProducts: {
      data: [
        createProduct('rec-1', 'Recommended Product 1', '79.99'),
        createProduct('rec-2', 'Recommended Product 2', '129.99'),
        createProduct('rec-3', 'Recommended Product 3', '129.99'),
        createProduct('rec-4', 'Recommended Product 4', '29.99'),
        createProduct('rec-5', 'Recommended Product 5', '39.99'),
        createProduct('rec-6', 'Recommended Product 6', '49.99'),
        createProduct('rec-7', 'Recommended Product 7', '59.99'),
        createProduct('rec-8', 'Recommended Product 8', '69.99'),
        createProduct('rec-9', 'Recommended Product 9', '129.99'),
      ],
      pageInfo: createPagination(),
    },
    getRecommendedShops: {
      data: [
        createShop('shop-1', 'Amazing Store'),
        createShop('shop-2', 'Best Deals Shop'),
      ],
      pageInfo: createPagination(),
    },
    searchProductsByShop: {
      data: [
        createProduct('search-1', 'Search Result 1', '59.99'),
        createProduct('search-2', 'Search Result 2', '89.99'),
      ],
      pageInfo: createPagination(),
    },
    getOrders: {
      data: [
        {
          id: 'order-1',
          name: '#1001',
          lineItems: [
            {
              productTitle: 'Sample Product',
              variantTitle: 'Medium',
              quantity: 2,
              product: null,
            },
          ],
          shop: createShop('shop-1', 'Sample Shop'),
        },
      ],
      pageInfo: createPagination(),
    },
    getBuyerAttributes: {
      data: {
        genderAffinity: 'NEUTRAL' as Gender,
        categoryAffinities: [
          {id: 'cat1', name: 'Electronics'},
          {id: 'cat2', name: 'Clothing'},
        ],
      },
    },
    showFeedbackSheet: undefined,
    getPopularProducts: {
      data: [
        createProduct('pop-1', 'The Hero Snowboard', '702.95'),
        createProduct('pop-2', 'Snow Jacket', '605.95', '702.00'),
        createProduct('pop-3', 'Winter Gloves', '89.95'),
        createProduct('pop-4', 'Summer Gloves', '89.95'),
        createProduct('pop-5', 'Spring Gloves', '89.95'),
        createProduct('pop-6', 'Playstation 5', '499.95'),
        createProduct('pop-7', 'Xbox Series X', '499.95'),
        createProduct('pop-8', 'Nintendo Switch', '299.95'),
        createProduct('pop-9', 'Playstation 4', '299.95'),
        createProduct('pop-10', 'Nintendo 3DS', '89.95'),
      ],
      pageInfo: createPagination(),
    },
    share: {
      message: 'Shared!',
      success: true,
    },
    shareSingle: {
      message: 'Shared!',
      success: true,
    },
    getCuratedProducts: {
      data: [
        createProduct('cur-1', 'Curated Product 1', '79.99'),
        createProduct('cur-2', 'Curated Product 2', '129.99'),
      ],
      pageInfo: createPagination(),
    },
    getSavedProducts: {
      data: [createProduct('saved-1', 'Saved Product 1', '49.99')],
      pageInfo: createPagination(),
    },
    getRecentProducts: {
      data: [createProduct('recent-1', 'Recent Product 1', '59.99')],
      pageInfo: createPagination(),
    },
    getProductSearch: {
      data: [createProduct('search-3', 'Search Product 3', '39.99')],
      pageInfo: createPagination(),
    },
    getProducts: {data: [createProduct('prod-2', 'Product 2', '19.99')]},
    getProduct: {data: createProduct('prod-1', 'Sample Product')},
    getProductVariants: {
      data: [
        {
          id: 'variant-1',
          title: 'Variant 1',
          isFavorited: false,
          image: {url: 'https://example.com/variant-1.jpg'},
          price: {amount: '19.99', currencyCode: 'USD'},
          compareAtPrice: {amount: '29.99', currencyCode: 'USD'},
        },
      ],
      pageInfo: createPagination(),
    },
    getProductMedia: {
      data: [
        {
          id: 'media-1',
          image: {url: 'https://example.com/media-1.jpg'},
          mediaContentType: 'IMAGE',
          alt: 'Sample product image',
        },
      ],
      pageInfo: createPagination(),
    },
    getShop: {data: createShop('shop-1', 'Sample Shop')},
    getRecentShops: {
      data: [createShop('recent-shop-1', 'Recent Shop 1')],
      pageInfo: createPagination(),
    },
    getFollowedShops: {
      data: [createShop('followed-shop-1', 'Followed Shop 1')],
      pageInfo: createPagination(),
    },
    previewProductInAr: undefined,
    createContent: {
      data: {
        publicId: 'content-123',
        externalId: null,
        image: {
          id: 'img-123',
          url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',
          width: 800,
          height: 600,
        },
        title: 'Mock Content',
        description: 'This is a mock content item',
        visibility: ['DISCOVERABLE'],
        shareableUrl: 'https://example.com/content/123',
        products: null,
      },
    },
    getContent: {
      data: [
        {
          publicId: 'content-123',
          image: {
            id: 'img-123',
            url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',
            width: 800,
            height: 600,
          },
          title: 'Mock Content',
          visibility: ['DISCOVERABLE'],
          status: MinisContentStatus.READY,
        },
      ],
    },
    generateUserToken: {
      data: {
        token: 'user-token-123',
        expiresAt: '2025-01-01',
        userState: UserState.VERIFIED,
      },
    },
    navigateToCart: undefined,
    requestPermission: {
      granted: true,
    },
    reportError: undefined,
  } as const

  const mock: Partial<ShopActions> = {}
  for (const key in results) {
    if (Object.prototype.hasOwnProperty.call(results, key)) {
      // @ts-expect-error: dynamic assignment is safe due to exhaustive mapping
      mock[key] = makeMockMethod(
        key as keyof ShopActions,
        results[key as keyof typeof results]
      )
    }
  }
  return mock as ShopActions
}

// Detect if running on a mobile device
const isMobile = (): boolean => {
  const userAgent = navigator.userAgent.toLowerCase()
  const isIOS = /iphone|ipad|ipod/.test(userAgent)
  const isAndroid = /android/.test(userAgent)

  return isIOS || isAndroid
}

export const injectMocks = ({force}: {force?: boolean} = {}) => {
  // Only inject mocks if we aren't on a mobile device or we force it
  if (isMobile() && !force) {
    return
  }

  if (!window.minisSDK) {
    window.minisSDK = makeMockActions()
    window.minisParams = {
      handle: 'mock-handle',
      initialUrl: '/mock-initial-url',
      platform: 'web',
    }
  }
}
