import type { Fill, Stroke } from './scene-graph'
import type { Color } from './types'

export const IS_BROWSER = typeof window !== 'undefined'
export const IS_TAURI = IS_BROWSER && '__TAURI_INTERNALS__' in window

export const BLACK: Color = { r: 0, g: 0, b: 0, a: 1 }
export const TRANSPARENT: Color = { r: 0, g: 0, b: 0, a: 0 }
export const DEFAULT_SHADOW_COLOR: Color = { r: 0, g: 0, b: 0, a: 0.25 }
export const SELECTION_COLOR = { r: 0.23, g: 0.51, b: 0.96, a: 1 } satisfies Color
export const COMPONENT_COLOR = { r: 0.592, g: 0.278, b: 1, a: 1 } satisfies Color
export const SNAP_COLOR = { r: 1.0, g: 0.0, b: 0.56, a: 1 } satisfies Color
export const CANVAS_BG_COLOR = { r: 0.96, g: 0.96, b: 0.96, a: 1 } satisfies Color
export const CANVAS_BG_COLOR_DARK = { r: 0.173, g: 0.173, b: 0.173, a: 1 } satisfies Color // #2c2c2c, Figma-ish dark canvas

/**
 * Returns the canvas background to initialize new pages with. Defers
 * to the OS `prefers-color-scheme` so users on a dark desktop don't
 * get a white flash every time they open a document.
 *
 * NOTE: this is deliberately the runtime/new-page path only. The
 * `.fig` serialization path continues to write the static light
 * `CANVAS_BG_COLOR` so files stay portable — a dark-theme user saving
 * a file must not force darkness on recipients.
 */
export function getDefaultCanvasBgColor(): Color {
  if (IS_BROWSER) {
    const params = new URLSearchParams(window.location.search)
    if ('env' in import.meta && import.meta.env.DEV && params.has('test')) {
      return CANVAS_BG_COLOR
    }
  }

  if (
    IS_BROWSER &&
    typeof window.matchMedia === 'function' &&
    window.matchMedia('(prefers-color-scheme: dark)').matches
  ) {
    return CANVAS_BG_COLOR_DARK
  }
  return CANVAS_BG_COLOR
}

export const SNAP_THRESHOLD = 5

export const RULER_SIZE = 20
export const RULER_BG_COLOR = { r: 0.14, g: 0.14, b: 0.14, a: 1 } satisfies Color
export const RULER_TICK_COLOR = { r: 0.4, g: 0.4, b: 0.4, a: 1 } satisfies Color
export const RULER_TEXT_COLOR = { r: 0.55, g: 0.55, b: 0.55, a: 1 } satisfies Color
export const RULER_BADGE_HEIGHT = 14
export const RULER_BADGE_PADDING = 3
export const RULER_BADGE_RADIUS = 2
export const RULER_BADGE_EXCLUSION = 30
export const RULER_TEXT_BASELINE = 0.65
export const RULER_MAJOR_TICK = 0.5
export const RULER_MINOR_TICK = 0.25
export const RULER_HIGHLIGHT_ALPHA = 0.3

export const PEN_HANDLE_RADIUS = 2.5
export const PEN_VERTEX_RADIUS = 3
export const PEN_CLOSE_RADIUS_BOOST = 2
export const PEN_PATH_STROKE_WIDTH = 2
export const PARENT_OUTLINE_ALPHA = 0.5
export const PARENT_OUTLINE_DASH = 4
export const DEFAULT_FONT_FAMILY = 'Inter'
export const DEFAULT_FONT_SIZE = 14
export const DEFAULT_STROKE_MITER_LIMIT = 4
export const LABEL_FONT_SIZE = 11
export const SIZE_FONT_SIZE = 10

export const HANDLE_HALF_SIZE = 3

export const LABEL_OFFSET_Y = 8
export const SIZE_PILL_PADDING_X = 6
export const SIZE_PILL_PADDING_Y = 6
export const SIZE_PILL_HEIGHT = 18
export const SIZE_PILL_RADIUS = 4
export const SIZE_PILL_TEXT_OFFSET_Y = 13

export const MARQUEE_FILL_ALPHA = 0.08
export const SELECTION_DASH_ALPHA = 0.6
export const DROP_HIGHLIGHT_ALPHA = 0.8
export const DROP_HIGHLIGHT_STROKE = 2

export const LAYOUT_INDICATOR_STROKE = 2
export const AUTO_LAYOUT_HOVER_TICK_LENGTH = 12
export const AUTO_LAYOUT_HOVER_STRIPE_GAP = 8
export const AUTO_LAYOUT_HOVER_STRIPE_WIDTH = 1
export const AUTO_LAYOUT_HOVER_STROKE_WIDTH = 1.5
export const AUTO_LAYOUT_HOVER_CHILD_DASH = 4
export const AUTO_LAYOUT_HOVER_VALUE_OFFSET = 18
export const AUTO_LAYOUT_HOVER_VALUE_PILL_HEIGHT = 22
export const AUTO_LAYOUT_HOVER_VALUE_PILL_RADIUS = 5
export const AUTO_LAYOUT_HOVER_VALUE_PILL_PADDING_X = 5
export const AUTO_LAYOUT_HOVER_GAP_REGION_TOLERANCE = 12
export const AUTO_LAYOUT_HOVER_TICK_HIT_TOLERANCE = 8
export const AUTO_LAYOUT_HOVER_PADDING_REGION_TOLERANCE = 20
export const AUTO_LAYOUT_PADDING_EDITOR_OFFSET_X = 18
export const AUTO_LAYOUT_PADDING_EDITOR_OFFSET_Y = 36
export const AUTO_LAYOUT_HOVER_BLUE = { r: 0.28, g: 0.64, b: 1, a: 0.82 } satisfies Color
export const AUTO_LAYOUT_HOVER_BLUE_FILL = { r: 0.28, g: 0.64, b: 1, a: 0.1 } satisfies Color
export const AUTO_LAYOUT_HOVER_MAGENTA = { r: 1, g: 0.32, b: 0.68, a: 0.78 } satisfies Color
export const AUTO_LAYOUT_HOVER_MAGENTA_FILL = { r: 1, g: 0.32, b: 0.68, a: 0.1 } satisfies Color

export const SECTION_CORNER_RADIUS = 5
export const SECTION_TITLE_HEIGHT = 24
export const SECTION_TITLE_PADDING_X = 8
export const SECTION_TITLE_RADIUS = 5
export const SECTION_TITLE_FONT_SIZE = 12
export const SECTION_TITLE_GAP = 6

export const COMPONENT_SET_DASH = 6
export const COMPONENT_SET_DASH_GAP = 4
export const COMPONENT_SET_BORDER_WIDTH = 1.5
export const COMPONENT_LABEL_FONT_SIZE = 11
export const COMPONENT_LABEL_GAP = 6
export const COMPONENT_LABEL_ICON_SIZE = 10
export const COMPONENT_LABEL_ICON_GAP = 4

export const RULER_TARGET_PIXEL_SPACING = 100
export const RULER_MAJOR_TOLERANCE = 0.01

export const FLASH_COLOR = SELECTION_COLOR
export const FLASH_ATTACK_MS = 200
export const FLASH_HOLD_MS = 400
export const FLASH_RELEASE_MS = 300
export const FLASH_STROKE_WIDTH = 2
export const FLASH_PADDING = 5
export const FLASH_OVERSHOOT = 30
export const FLASH_RADIUS = 4

export const AI_ACTIVE_COLOR = { r: 0.26, g: 0.52, b: 0.96 }
export const AI_DONE_COLOR = { r: 0.16, g: 0.73, b: 0.36 }
export const AI_PULSE_PERIOD_MS = 1500
export const AI_DONE_DURATION_MS = 800

export const TEXT_SELECTION_COLOR = { r: 0.26, g: 0.52, b: 0.96, a: 0.3 }
export const TEXT_CARET_COLOR = BLACK
export const TEXT_CARET_WIDTH = 1

export type ACPAgentID = 'claude-code' | 'codex' | 'gemini-cli'

export interface ACPAgentDef {
  id: ACPAgentID
  name: string
  command: string
  args: string[]
  installCommand?: string
}

export const ACP_AGENTS: ACPAgentDef[] = [
  {
    id: 'claude-code',
    name: 'Claude Code',
    command: 'claude-agent-acp',
    args: [],
    installCommand: 'npm i -g @agentclientprotocol/claude-agent-acp'
  },
  {
    id: 'codex',
    name: 'Codex',
    command: 'codex-acp',
    args: [],
    installCommand: 'npm i -g @zed-industries/codex-acp'
  },
  {
    id: 'gemini-cli',
    name: 'Gemini CLI',
    command: 'gemini',
    args: ['--acp'],
    installCommand: 'npm i -g @google/gemini-cli'
  }
]

export type AIProviderID =
  | 'openrouter'
  | 'anthropic'
  | 'openai'
  | 'google'
  | 'deepseek'
  | 'openai-compatible'
  | 'zai'
  | 'minimax'
  | 'anthropic-compatible'
  | `acp:${ACPAgentID}`

export interface ModelOption {
  id: string
  name: string
  tag?: string
}

export interface AIProviderDef {
  id: AIProviderID
  name: string
  keyPlaceholder: string
  keyURL: string
  models: ModelOption[]
  defaultModel: string
  supportsCustomBaseURL?: boolean
  supportsCustomModel?: boolean
}

export const AI_PROVIDERS: AIProviderDef[] = [
  {
    id: 'openrouter',
    name: 'OpenRouter',
    keyPlaceholder: 'sk-or-…',
    keyURL: 'https://openrouter.ai/keys',
    defaultModel: 'anthropic/claude-sonnet-4.6',
    supportsCustomModel: true,
    models: [
      { id: 'anthropic/claude-sonnet-4.6', name: 'Claude Sonnet 4.6', tag: 'Best for design' },
      { id: 'anthropic/claude-opus-4.6', name: 'Claude Opus 4.6', tag: 'Smartest' },
      { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', tag: 'Vision + code' },
      {
        id: 'google/gemini-3.1-pro-preview',
        name: 'Gemini 3.1 Pro',
        tag: '1M context'
      },
      { id: 'openai/gpt-5.3-codex', name: 'GPT-5.3 Codex' },
      { id: 'google/gemini-3-flash-preview', name: 'Gemini 3 Flash', tag: 'Fast' },
      { id: 'deepseek/deepseek-v3.2', name: 'DeepSeek V3.2', tag: 'Cheap' },
      { id: 'qwen/qwen3.5-flash-02-23', name: 'Qwen 3.5 Flash', tag: 'Cheap' },
      { id: 'qwen/qwen3-coder:free', name: 'Qwen3 Coder', tag: 'Free' },
      { id: 'openai/gpt-oss-120b:free', name: 'GPT-OSS 120B', tag: 'Free' }
    ]
  },
  {
    id: 'anthropic',
    name: 'Anthropic',
    keyPlaceholder: 'sk-ant-…',
    keyURL: 'https://console.anthropic.com/settings/keys',
    defaultModel: 'claude-sonnet-4-6-20260301',
    models: [
      { id: 'claude-sonnet-4-6-20260301', name: 'Claude Sonnet 4.6', tag: 'Best for design' },
      { id: 'claude-opus-4-6-20260301', name: 'Claude Opus 4.6', tag: 'Smartest' }
    ]
  },
  {
    id: 'openai',
    name: 'OpenAI',
    keyPlaceholder: 'sk-…',
    keyURL: 'https://platform.openai.com/api-keys',
    defaultModel: 'gpt-5.3-codex',
    models: [
      { id: 'gpt-5.3-codex', name: 'GPT-5.3 Codex' },
      { id: 'gpt-4.1', name: 'GPT-4.1' },
      { id: 'o3', name: 'o3', tag: 'Reasoning' },
      { id: 'o4-mini', name: 'o4-mini', tag: 'Fast reasoning' }
    ]
  },
  {
    id: 'google',
    name: 'Google AI',
    keyPlaceholder: 'AIza…',
    keyURL: 'https://aistudio.google.com/apikey',
    defaultModel: 'gemini-3.1-pro-preview',
    models: [
      { id: 'gemini-3.1-pro-preview', name: 'Gemini 3.1 Pro', tag: '1M context' },
      { id: 'gemini-3-flash-preview', name: 'Gemini 3 Flash', tag: 'Fast' }
    ]
  },
  {
    id: 'deepseek',
    name: 'DeepSeek',
    keyPlaceholder: 'sk-…',
    keyURL: 'https://platform.deepseek.com/api_keys',
    defaultModel: 'deepseek-v4-flash',
    models: [
      { id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash', tag: 'Fast' },
      { id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro', tag: 'Reasoning' }
    ]
  },
  {
    id: 'zai',
    name: 'Z.ai',
    keyPlaceholder: 'API key',
    keyURL: 'https://docs.z.ai/devpack/quick-start',
    defaultModel: 'glm-5.1',
    models: [
      { id: 'glm-5.1', name: 'GLM-5.1', tag: 'Best' },
      { id: 'glm-5', name: 'GLM-5' },
      { id: 'glm-5-code', name: 'GLM-5-Code' },
      { id: 'glm-4.7', name: 'GLM-4.7' },
      { id: 'glm-4.7-flashx', name: 'GLM-4.7-FlashX' },
      { id: 'glm-4.6', name: 'GLM-4.6' },
      { id: 'glm-4.5', name: 'GLM-4.5' },
      { id: 'glm-4.5-x', name: 'GLM-4.5-X' },
      { id: 'glm-4.5-air', name: 'GLM-4.5-Air' },
      { id: 'glm-4.5-airx', name: 'GLM-4.5-AirX' },
      { id: 'glm-4-32b-0414-128k', name: 'GLM-4-32B-0414-128K' },
      { id: 'glm-4.7-flash', name: 'GLM-4.7-Flash', tag: 'Free' },
      { id: 'glm-4.5-flash', name: 'GLM-4.5-Flash', tag: 'Free' }
    ]
  },
  {
    id: 'minimax',
    name: 'MiniMax',
    keyPlaceholder: 'API key',
    keyURL: 'https://platform.minimax.io/user-center/basic-information/interface-key',
    defaultModel: 'MiniMax-M2.7',
    models: [
      { id: 'MiniMax-M2.7', name: 'MiniMax-M2.7', tag: 'Best' },
      { id: 'MiniMax-M2.7-highspeed', name: 'MiniMax-M2.7-highspeed', tag: 'Fast' },
      { id: 'MiniMax-M2.5', name: 'MiniMax-M2.5' },
      { id: 'MiniMax-M2.5-highspeed', name: 'MiniMax-M2.5 Highspeed', tag: 'Fast' },
      { id: 'MiniMax-M2.1', name: 'MiniMax-M2.1' },
      { id: 'MiniMax-M2.1-highspeed', name: 'MiniMax-M2.1 Highspeed', tag: 'Fast' },
      { id: 'MiniMax-M2', name: 'MiniMax-M2' }
    ]
  },
  {
    id: 'openai-compatible',
    name: 'OpenAI-compatible',
    keyPlaceholder: 'API key',
    keyURL: '',
    defaultModel: '',
    models: [],
    supportsCustomBaseURL: true,
    supportsCustomModel: true
  },
  {
    id: 'anthropic-compatible',
    name: 'Anthropic-compatible',
    keyPlaceholder: 'API key',
    keyURL: '',
    defaultModel: '',
    models: [],
    supportsCustomBaseURL: true,
    supportsCustomModel: true
  }
]

export const DEFAULT_AI_PROVIDER: AIProviderID = 'openrouter'
export const DEFAULT_AI_MODEL = AI_PROVIDERS[0].defaultModel

export const AUTOMATION_HTTP_PORT = 7600
export const AUTOMATION_WS_PORT = 7601

export const GOOGLE_FONTS_API_KEY = 'AIzaSyD1tYDR_dUEiV-Tw1vksEhZbUytgKW5pc8'

export const CJK_FALLBACK_FAMILIES_MACOS = [
  'PingFang SC',
  'Hiragino Sans',
  'Apple SD Gothic Neo',
  'Heiti SC'
]

export const CJK_FALLBACK_FAMILIES_WINDOWS = [
  'Microsoft YaHei',
  'Microsoft YaHei UI',
  'Microsoft JhengHei',
  'Yu Gothic',
  'Malgun Gothic',
  'SimHei',
  'SimSun'
]

export const CJK_FALLBACK_FAMILIES_LINUX = [
  'Noto Sans CJK SC',
  'Noto Sans CJK JP',
  'Noto Sans CJK KR',
  'WenQuanYi Micro Hei',
  'Droid Sans Fallback'
]

export const CJK_GOOGLE_FONTS = ['Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR']

export const DEFAULT_SHAPE_FILL: Fill = {
  type: 'SOLID',
  color: { r: 0.83, g: 0.83, b: 0.83, a: 1 },
  opacity: 1,
  visible: true
}

export const DEFAULT_FRAME_FILL: Fill = {
  type: 'SOLID',
  color: { r: 1, g: 1, b: 1, a: 1 },
  opacity: 1,
  visible: true
}

export const SECTION_DEFAULT_FILL: Fill = {
  type: 'SOLID',
  color: { r: 0.37, g: 0.37, b: 0.37, a: 1 },
  opacity: 1,
  visible: true
}

export const SECTION_DEFAULT_STROKE: Stroke = {
  color: { r: 0.55, g: 0.55, b: 0.55, a: 1 },
  weight: 1,
  opacity: 1,
  visible: true,
  align: 'INSIDE'
}

export const ZOOM_DIVISOR = 50
export const ZOOM_SCALE_MIN = 0.75
export const ZOOM_SCALE_MAX = 1.25

export const PEN_CLOSE_THRESHOLD = 8
export const ROTATION_SNAP_DEGREES = 15
export const CORNER_ROTATE_ZONE = 16
export const HANDLE_HIT_RADIUS = 6
export const DEFAULT_TEXT_WIDTH = 200
export const DEFAULT_TEXT_HEIGHT = 24
export const AUTO_LAYOUT_BREAK_THRESHOLD = 8
