import type {
  GoogleMapsPlaceDetailsParams,
  GoogleMapsPlaceDetailsResponse,
} from '@/tools/google_maps/types'
import type { ToolConfig } from '@/tools/types'

export const googleMapsPlaceDetailsTool: ToolConfig<
  GoogleMapsPlaceDetailsParams,
  GoogleMapsPlaceDetailsResponse
> = {
  id: 'google_maps_place_details',
  name: 'Google Maps Place Details',
  description: 'Get detailed information about a specific place',
  version: '1.0.0',

  params: {
    apiKey: {
      type: 'string',
      required: true,
      visibility: 'user-only',
      description: 'Google Maps API key',
    },
    placeId: {
      type: 'string',
      required: true,
      visibility: 'user-or-llm',
      description: 'Google Place ID',
    },
    fields: {
      type: 'string',
      required: false,
      visibility: 'user-or-llm',
      description: 'Comma-separated list of fields to return',
    },
    language: {
      type: 'string',
      required: false,
      visibility: 'user-or-llm',
      description: 'Language code for results (e.g., en, es, fr)',
    },
  },

  hosting: {
    envKeyPrefix: 'GOOGLE_CLOUD_API_KEY',
    apiKeyParam: 'apiKey',
    byokProviderId: 'google_cloud',
    pricing: {
      type: 'per_request',
      cost: 0.017,
    },
    rateLimit: {
      mode: 'per_request',
      requestsPerMinute: 60,
    },
  },

  request: {
    url: (params) => {
      const url = new URL('https://maps.googleapis.com/maps/api/place/details/json')
      url.searchParams.set('place_id', params.placeId.trim())
      url.searchParams.set('key', params.apiKey.trim())

      // Default fields if not specified - comprehensive list
      const fields =
        params.fields ||
        'place_id,name,formatted_address,geometry,types,rating,user_ratings_total,price_level,website,formatted_phone_number,international_phone_number,opening_hours,reviews,photos,url,utc_offset,vicinity,business_status'
      url.searchParams.set('fields', fields)

      if (params.language) {
        url.searchParams.set('language', params.language.trim())
      }

      return url.toString()
    },
    method: 'GET',
    headers: () => ({
      'Content-Type': 'application/json',
    }),
  },

  transformResponse: async (response: Response) => {
    const data = await response.json()

    if (data.status !== 'OK') {
      throw new Error(
        `Place details request failed: ${data.status} - ${data.error_message || 'Unknown error'}`
      )
    }

    const place = data.result

    const reviews = (place.reviews || []).map(
      (review: {
        author_name: string
        author_url?: string
        profile_photo_url?: string
        rating: number
        text: string
        time: number
        relative_time_description: string
      }) => ({
        authorName: review.author_name,
        authorUrl: review.author_url ?? null,
        profilePhotoUrl: review.profile_photo_url ?? null,
        rating: review.rating,
        text: review.text,
        time: review.time,
        relativeTimeDescription: review.relative_time_description,
      })
    )

    const photos = (place.photos || []).map(
      (photo: {
        photo_reference: string
        height: number
        width: number
        html_attributions: string[]
      }) => ({
        photoReference: photo.photo_reference,
        height: photo.height,
        width: photo.width,
        htmlAttributions: photo.html_attributions ?? [],
      })
    )

    // Destructure opening hours
    const openNow = place.opening_hours?.open_now ?? null
    const weekdayText = place.opening_hours?.weekday_text ?? []

    // Extract location
    const lat = place.geometry?.location?.lat ?? null
    const lng = place.geometry?.location?.lng ?? null

    return {
      success: true,
      output: {
        placeId: place.place_id,
        name: place.name ?? null,
        formattedAddress: place.formatted_address ?? null,
        lat,
        lng,
        types: place.types ?? [],
        rating: place.rating ?? null,
        userRatingsTotal: place.user_ratings_total ?? null,
        priceLevel: place.price_level ?? null,
        website: place.website ?? null,
        phoneNumber: place.formatted_phone_number ?? null,
        internationalPhoneNumber: place.international_phone_number ?? null,
        openNow,
        weekdayText,
        reviews,
        photos,
        url: place.url ?? null,
        utcOffset: place.utc_offset ?? null,
        vicinity: place.vicinity ?? null,
        businessStatus: place.business_status ?? null,
      },
    }
  },

  outputs: {
    placeId: {
      type: 'string',
      description: 'Google Place ID',
    },
    name: {
      type: 'string',
      description: 'Place name',
      optional: true,
    },
    formattedAddress: {
      type: 'string',
      description: 'Formatted street address',
      optional: true,
    },
    lat: {
      type: 'number',
      description: 'Latitude coordinate',
      optional: true,
    },
    lng: {
      type: 'number',
      description: 'Longitude coordinate',
      optional: true,
    },
    types: {
      type: 'array',
      description: 'Place types (e.g., restaurant, cafe)',
      items: {
        type: 'string',
      },
    },
    rating: {
      type: 'number',
      description: 'Average rating (1.0 to 5.0)',
      optional: true,
    },
    userRatingsTotal: {
      type: 'number',
      description: 'Total number of user ratings',
      optional: true,
    },
    priceLevel: {
      type: 'number',
      description: 'Price level (0=Free, 1=Inexpensive, 2=Moderate, 3=Expensive, 4=Very Expensive)',
      optional: true,
    },
    website: {
      type: 'string',
      description: 'Place website URL',
      optional: true,
    },
    phoneNumber: {
      type: 'string',
      description: 'Local formatted phone number',
      optional: true,
    },
    internationalPhoneNumber: {
      type: 'string',
      description: 'International formatted phone number',
      optional: true,
    },
    openNow: {
      type: 'boolean',
      description: 'Whether the place is currently open',
      optional: true,
    },
    weekdayText: {
      type: 'array',
      description: 'Opening hours formatted by day of week',
      items: {
        type: 'string',
      },
    },
    reviews: {
      type: 'array',
      description: 'User reviews (up to 5 most relevant)',
      items: {
        type: 'object',
        properties: {
          authorName: { type: 'string', description: 'Reviewer name' },
          authorUrl: { type: 'string', description: 'Reviewer profile URL', optional: true },
          profilePhotoUrl: { type: 'string', description: 'Reviewer photo URL', optional: true },
          rating: { type: 'number', description: 'Rating given (1-5)' },
          text: { type: 'string', description: 'Review text' },
          time: { type: 'number', description: 'Review timestamp (Unix epoch)' },
          relativeTimeDescription: {
            type: 'string',
            description: 'Relative time (e.g., "a month ago")',
          },
        },
      },
    },
    photos: {
      type: 'array',
      description: 'Place photos',
      items: {
        type: 'object',
        properties: {
          photoReference: { type: 'string', description: 'Photo reference for Place Photos API' },
          height: { type: 'number', description: 'Photo height in pixels' },
          width: { type: 'number', description: 'Photo width in pixels' },
          htmlAttributions: { type: 'array', description: 'Required attributions' },
        },
      },
    },
    url: {
      type: 'string',
      description: 'Google Maps URL for the place',
      optional: true,
    },
    utcOffset: {
      type: 'number',
      description: 'UTC offset in minutes',
      optional: true,
    },
    vicinity: {
      type: 'string',
      description: 'Simplified address (neighborhood/street)',
      optional: true,
    },
    businessStatus: {
      type: 'string',
      description: 'Business status (OPERATIONAL, CLOSED_TEMPORARILY, CLOSED_PERMANENTLY)',
      optional: true,
    },
  },
}
