'use client'

import { useMemo } from 'react'
import type { Node, Edge } from 'reactflow'
import { MarkerType } from 'reactflow'
import { SDK_FLOW_STEPS, FLOW_PACKAGES, type SDKFlowStep } from '../flow-data'
import {
  NODE_WIDTH,
  PACKAGE_X_OFFSET,
  STEP_Y_START,
  completionColor,
  getStepPosition,
  type PackageFilter,
} from './helpers'

export function useFlowGraph(
  packageFilter: PackageFilter,
  showDb: boolean,
  showRag: boolean,
  selectedStep: SDKFlowStep | null,
): { nodes: Node[]; edges: Edge[] } {
  return useMemo(() => {
    const nodes: Node[] = []
    const edges: Edge[] = []

    const visibleSteps =
      packageFilter === 'alle'
        ? SDK_FLOW_STEPS
        : SDK_FLOW_STEPS.filter(s => s.package === packageFilter)

    const visibleStepIds = new Set(visibleSteps.map(s => s.id))

    // Step Nodes
    visibleSteps.forEach(step => {
      const pkg = FLOW_PACKAGES[step.package]
      const pos = getStepPosition(step)
      const isSelected = selectedStep?.id === step.id

      // Checkpoint badge text
      let badge = ''
      if (step.checkpointId) {
        badge = step.checkpointType === 'REQUIRED' ? ' *' : ' ~'
        if (step.checkpointReviewer && step.checkpointReviewer !== 'NONE') {
          badge += ` [${step.checkpointReviewer}]`
        }
      }

      nodes.push({
        id: step.id,
        type: 'default',
        position: pos,
        data: {
          label: (
            <div className="text-center px-1">
              <div className="font-medium text-xs leading-tight">
                {step.nameShort}
              </div>
              <div className="text-[10px] opacity-70 mt-0.5">
                {step.checkpointId || ''}
                {badge}
              </div>
              {step.completion !== undefined && (
                <div className="mt-1.5 px-1">
                  <div
                    className="flex items-center justify-center gap-1 text-[9px] font-bold mb-0.5"
                    style={{ color: isSelected ? 'rgba(255,255,255,0.9)' : completionColor(step.completion) }}
                  >
                    {step.completion}%
                  </div>
                  <div
                    className="h-1 rounded-full overflow-hidden"
                    style={{ background: isSelected ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.1)' }}
                  >
                    <div
                      className="h-full rounded-full"
                      style={{
                        width: `${step.completion}%`,
                        background: isSelected ? 'rgba(255,255,255,0.8)' : completionColor(step.completion),
                      }}
                    />
                  </div>
                </div>
              )}
            </div>
          ),
        },
        style: {
          background: isSelected ? pkg.color.border : pkg.color.bg,
          color: isSelected ? 'white' : pkg.color.text,
          border: `2px solid ${pkg.color.border}`,
          borderRadius: '10px',
          padding: '8px 4px',
          minWidth: `${NODE_WIDTH}px`,
          maxWidth: `${NODE_WIDTH}px`,
          cursor: 'pointer',
          boxShadow: isSelected
            ? `0 0 16px ${pkg.color.border}`
            : '0 1px 3px rgba(0,0,0,0.08)',
          opacity: step.isOptional ? 0.85 : 1,
          borderStyle: step.isOptional ? 'dashed' : 'solid',
        },
      })
    })

    // Prerequisite Edges
    visibleSteps.forEach(step => {
      step.prerequisiteSteps.forEach(preId => {
        if (visibleStepIds.has(preId)) {
          edges.push({
            id: `e-${preId}-${step.id}`,
            source: preId,
            target: step.id,
            type: 'smoothstep',
            animated: selectedStep?.id === preId || selectedStep?.id === step.id,
            style: {
              stroke:
                selectedStep?.id === preId || selectedStep?.id === step.id
                  ? '#7c3aed'
                  : '#94a3b8',
              strokeWidth:
                selectedStep?.id === preId || selectedStep?.id === step.id
                  ? 2.5
                  : 1.5,
            },
            markerEnd: {
              type: MarkerType.ArrowClosed,
              color:
                selectedStep?.id === preId || selectedStep?.id === step.id
                  ? '#7c3aed'
                  : '#94a3b8',
              width: 14,
              height: 14,
            },
          })
        }
      })
    })

    // DB Table Nodes
    if (showDb) {
      const dbTablesInUse = new Set<string>()
      visibleSteps.forEach(s => s.dbTables.forEach(t => dbTablesInUse.add(t)))

      let dbIdx = 0
      dbTablesInUse.forEach(table => {
        const nodeId = `db-${table}`
        nodes.push({
          id: nodeId,
          type: 'default',
          position: { x: -280, y: STEP_Y_START + dbIdx * 90 },
          data: {
            label: (
              <div className="text-center">
                <div className="text-sm mb-0.5">DB</div>
                <div className="font-medium text-[10px] leading-tight">{table}</div>
              </div>
            ),
          },
          style: {
            background: '#f1f5f9',
            color: '#475569',
            border: '2px solid #94a3b8',
            borderRadius: '50%',
            width: '90px',
            height: '90px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            padding: '4px',
          },
        })

        // Connect steps to this DB table
        visibleSteps
          .filter(s => s.dbTables.includes(table))
          .forEach(step => {
            edges.push({
              id: `e-db-${table}-${step.id}`,
              source: nodeId,
              target: step.id,
              type: 'straight',
              style: {
                stroke: '#94a3b8',
                strokeWidth: 1,
                strokeDasharray: '6 3',
              },
              labelStyle: { fontSize: 9, fill: '#94a3b8' },
              label: step.dbMode !== 'none' ? step.dbMode : undefined,
            })
          })

        dbIdx++
      })
    }

    // RAG Collection Nodes
    if (showRag) {
      const ragInUse = new Set<string>()
      visibleSteps.forEach(s => s.ragCollections.forEach(r => ragInUse.add(r)))

      let ragIdx = 0
      ragInUse.forEach(collection => {
        const nodeId = `rag-${collection}`

        // Place RAG nodes to the right of all packages
        const rightX = (packageFilter === 'alle' ? 1280 : PACKAGE_X_OFFSET[packageFilter] || 0) + NODE_WIDTH + 180
        nodes.push({
          id: nodeId,
          type: 'default',
          position: { x: rightX, y: STEP_Y_START + ragIdx * 90 },
          data: {
            label: (
              <div className="text-center">
                <div className="text-sm mb-0.5">RAG</div>
                <div className="font-medium text-[10px] leading-tight">
                  {collection.replace('bp_', '')}
                </div>
              </div>
            ),
          },
          style: {
            background: '#dcfce7',
            color: '#166534',
            border: '2px solid #22c55e',
            borderRadius: '50%',
            width: '90px',
            height: '90px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            padding: '4px',
          },
        })

        // Connect steps to this RAG collection
        visibleSteps
          .filter(s => s.ragCollections.includes(collection))
          .forEach(step => {
            edges.push({
              id: `e-rag-${collection}-${step.id}`,
              source: nodeId,
              target: step.id,
              type: 'straight',
              style: {
                stroke: '#22c55e',
                strokeWidth: 1,
                strokeDasharray: '6 3',
              },
            })
          })

        ragIdx++
      })
    }

    return { nodes, edges }
  }, [packageFilter, showDb, showRag, selectedStep])
}
