import * as ImagePicker from 'expo-image-picker'
import * as MediaLibrary from 'expo-media-library'
import { Linking, Platform } from 'react-native'
import { disclose } from 'src/state/permissionDisclosure'

/** Kind of permission being gated — surfaces the right label in the screen. */
export type PermissionKind = 'camera' | 'microphone' | 'mediaLibrary' | 'savePhotos'

export class PermissionDeniedError extends Error {
  constructor(public kind: PermissionKind) {
    super(`${kind} permission denied`)
    this.name = 'PermissionDeniedError'
  }
}

/** Imperative helper. Most screens should use the hook forms; this exists for
 *  pipelines that run before a component renders (e.g. pre-requesting the
 *  media-library permission before iOS pops its dialog mid-pick for videos). */
export async function ensureMediaLibraryPermission(): Promise<boolean> {
  const cur = await ImagePicker.getMediaLibraryPermissionsAsync()
  if (cur.granted) return true
  if (!cur.canAskAgain) throw new PermissionDeniedError('mediaLibrary')
  const next = await ImagePicker.requestMediaLibraryPermissionsAsync()
  if (next.granted) return true
  throw new PermissionDeniedError('mediaLibrary')
}

/** Add-only photo-library grant for SAVING media to the device (distinct from
 *  the read permission `ensureMediaLibraryPermission` uses for the composer's
 *  picker). `requestPermissionsAsync(true)` requests write-only access — on iOS
 *  this is the "…would like to add to your Photos" prompt (no full-library read).
 *
 *  Android is intentionally skipped: we save via MediaStore (no runtime
 *  permission on API 29+) and deliberately block READ_MEDIA_* to stay off
 *  Google Play's Photo & Video Permissions declaration, so requesting them here
 *  would spuriously report "denied". The save call surfaces any real failure. */
export async function ensureSavePhotosPermission(): Promise<boolean> {
  if (Platform.OS === 'android') return true
  const cur = await MediaLibrary.getPermissionsAsync(true)
  if (cur.granted) return true
  if (!cur.canAskAgain) throw new PermissionDeniedError('savePhotos')
  const next = await MediaLibrary.requestPermissionsAsync(true)
  if (next.granted) return true
  throw new PermissionDeniedError('savePhotos')
}

export async function ensureCameraPermission(): Promise<boolean> {
  const cur = await ImagePicker.getCameraPermissionsAsync()
  if (cur.granted) return true
  if (!cur.canAskAgain) throw new PermissionDeniedError('camera')
  // D.2 Android prominent-disclosure. iOS / already-disclosed paths
  // resolve synchronously without showing UI.
  await disclose('camera')
  const next = await ImagePicker.requestCameraPermissionsAsync()
  if (next.granted) return true
  throw new PermissionDeniedError('camera')
}

/** Routes the user to the system settings page for the current platform. */
export function openSystemSettings(): void {
  if (Platform.OS === 'ios') {
    Linking.openURL('app-settings:').catch(() => Linking.openSettings())
  } else {
    Linking.openSettings()
  }
}
