-- ═══════════════════════════════════════════════════════════════
-- INFINITH SaaS Schema V3: Multi-tenant, Time-series, Loop-ready
-- ═══════════════════════════════════════════════════════════════
--
-- Design Principles:
-- 1. CLINIC-CENTRIC: One clinic entity, many analysis runs
-- 2. TIME-SERIES: Channel metrics stored as snapshots over time
-- 3. SEPARATION: Raw data vs analyzed report vs strategy
-- 4. LOOP-READY: Each run builds on previous data for trend analysis
-- 5. MULTI-TENANT: user_id on everything for future auth
--
-- Data Flow:
--   clinics (병원 마스터)
--     └─ analysis_runs (분석 실행 히스토리)
--          ├─ channel_snapshots (채널별 시계열 데이터)
--          ├─ screenshots (스크린샷 증거)
--          └─ reports (AI 리포트)
--     └─ channel_configs (채널 연결 설정 - 핸들, 검증 상태)
--     └─ content_plans (콘텐츠 기획)

-- ─── 1. Clinics (병원 마스터 테이블) ───
-- 병원 1개 = 1행. URL이 달라도 같은 병원이면 같은 행.
CREATE TABLE IF NOT EXISTS clinics (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID,                          -- 나중에 auth.users.id 연결
  url TEXT NOT NULL,                     -- 대표 URL
  name TEXT NOT NULL,                    -- 한국어 병원명
  name_en TEXT,                          -- 영문 병원명
  domain TEXT,                           -- 도메인 (www 제외)
  address TEXT,
  phone TEXT,
  established_year INT,                  -- 개원 연도
  services TEXT[] DEFAULT '{}',          -- 시술 목록

  -- 브랜딩 (변경 빈도 낮음 → 병원 레벨에 저장)
  branding JSONB DEFAULT '{}',           -- colors, fonts, logo, tagline

  -- 채널 핸들 (마스터 — 검증 완료된 것들)
  -- 매 분석 시 discover-channels에서 업데이트
  social_handles JSONB DEFAULT '{}',     -- {instagram: ["@handle1"], youtube: "@handle", ...}
  verified_channels JSONB DEFAULT '{}',  -- Phase 1 결과 (캐시)

  -- 메타
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  last_analyzed_at TIMESTAMPTZ,          -- 마지막 분석 시간
  analysis_frequency TEXT DEFAULT 'manual', -- 'manual' | 'daily' | 'weekly' | 'monthly'

  UNIQUE(url)
);

-- ─── 2. Analysis Runs (분석 실행 히스토리) ───
-- 매 분석 1회 = 1행. 시간순으로 쌓임.
CREATE TABLE IF NOT EXISTS analysis_runs (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,

  -- 파이프라인 상태
  status TEXT DEFAULT 'pending'
    CHECK (status IN ('pending','discovering','collecting','generating','complete','partial','error')),
  pipeline_started_at TIMESTAMPTZ DEFAULT NOW(),
  pipeline_completed_at TIMESTAMPTZ,
  error_message TEXT,
  channel_errors JSONB DEFAULT '{}',     -- 채널별 에러 기록

  -- Phase 1 결과
  scrape_data JSONB DEFAULT '{}',        -- Firecrawl 원시 데이터
  discovered_channels JSONB DEFAULT '{}', -- 발견된 채널 목록

  -- Phase 2 결과 (원시 데이터 — 정규화 전)
  raw_channel_data JSONB DEFAULT '{}',   -- 모든 API 수집 원시 데이터
  analysis_data JSONB DEFAULT '{}',      -- 시장 분석 (Perplexity)
  vision_analysis JSONB DEFAULT '{}',    -- Vision 분석 결과

  -- Phase 3 결과
  report JSONB DEFAULT '{}',             -- AI 리포트 (최종)

  -- 메타
  trigger TEXT DEFAULT 'manual',         -- 'manual' | 'scheduled' | 'webhook'
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 3. Channel Snapshots (채널별 시계열 데이터) ───
-- 각 채널의 메트릭을 시간별로 쌓음. 트렌드 분석의 핵심.
-- 매 분석 시 채널별 1행씩 INSERT (UPDATE 아님!)
CREATE TABLE IF NOT EXISTS channel_snapshots (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  run_id UUID NOT NULL REFERENCES analysis_runs(id) ON DELETE CASCADE,

  channel TEXT NOT NULL,                 -- 'youtube' | 'instagram' | 'facebook' | 'gangnamUnni' | 'naverBlog' | 'naverPlace' | 'googleMaps' | 'website'
  handle TEXT,                           -- @handle 또는 URL

  -- 정량 메트릭 (채널별로 다르지만 공통 컬럼으로)
  followers INT,                         -- YouTube 구독자, Instagram 팔로워, Facebook 팔로워
  posts INT,                             -- 게시물 수, 영상 수
  total_views BIGINT,                    -- YouTube 총 조회수
  rating NUMERIC(3,1),                   -- 강남언니, Google Maps, Naver Place 평점
  rating_scale INT DEFAULT 10,           -- 5 또는 10
  reviews INT,                           -- 리뷰 수

  -- 채널별 상세 데이터 (JSONB)
  details JSONB DEFAULT '{}',            -- top videos, latest posts, doctors, etc.

  -- AI 점수
  health_score INT,                      -- 0-100 채널 건강도 점수
  health_status TEXT,                    -- 'excellent' | 'good' | 'warning' | 'critical'
  diagnosis JSONB DEFAULT '[]',          -- [{issue, severity, recommendation}]

  -- 스크린샷
  screenshot_url TEXT,                   -- Supabase Storage URL
  screenshot_caption TEXT,

  captured_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 4. Screenshots (스크린샷 증거) ───
CREATE TABLE IF NOT EXISTS screenshots (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  run_id UUID NOT NULL REFERENCES analysis_runs(id) ON DELETE CASCADE,

  channel TEXT NOT NULL,                 -- 어떤 채널의 스크린샷인지
  page_type TEXT,                        -- 'main' | 'doctors' | 'surgery' | 'landing'
  url TEXT NOT NULL,                     -- 스크린샷 이미지 URL (Supabase Storage)
  source_url TEXT,                       -- 원본 페이지 URL
  caption TEXT,

  -- Vision 분석 결과
  vision_data JSONB DEFAULT '{}',        -- Gemini Vision 추출 데이터

  captured_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 5. Content Plans (콘텐츠 기획) ───
-- 분석 결과를 기반으로 생성된 콘텐츠 기획. 매 분석마다 갱신 가능.
CREATE TABLE IF NOT EXISTS content_plans (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  run_id UUID REFERENCES analysis_runs(id),  -- 어떤 분석 기반인지

  -- 기획 데이터
  brand_guide JSONB DEFAULT '{}',        -- 브랜딩 가이드
  channel_strategies JSONB DEFAULT '[]', -- 채널별 전략 카드
  content_strategy JSONB DEFAULT '{}',   -- 콘텐츠 필라, 타입 매트릭스, 워크플로우
  calendar JSONB DEFAULT '{}',           -- 4주 캘린더
  asset_collection JSONB DEFAULT '{}',   -- 에셋 수집 현황

  -- 메타
  is_active BOOLEAN DEFAULT TRUE,        -- 현재 활성 기획인지
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 6. Channel Configs (채널 연결 설정) ───
-- 사용자가 직접 연결하거나 수정한 채널 정보. discover가 자동 탐지한 것과 별도.
CREATE TABLE IF NOT EXISTS channel_configs (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,

  channel TEXT NOT NULL,                 -- 'youtube' | 'instagram' | etc.
  handle TEXT NOT NULL,                  -- @handle 또는 URL
  is_verified BOOLEAN DEFAULT FALSE,     -- 사용자가 직접 확인한 경우
  is_active BOOLEAN DEFAULT TRUE,        -- 활성/비활성

  -- 연결 인증 (미래 — API 직접 연동 시)
  access_token TEXT,                     -- OAuth token (암호화 필요)
  token_expires_at TIMESTAMPTZ,

  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),

  UNIQUE(clinic_id, channel, handle)
);

-- ─── 7. Performance Metrics (성과 메트릭 — 주간 루프) ───
-- 각 분석 시 이전 분석과 비교하여 KPI 달성률을 계산.
-- Content Director가 이 데이터를 참조하여 다음 기획을 조정.
CREATE TABLE IF NOT EXISTS performance_metrics (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  run_id UUID NOT NULL REFERENCES analysis_runs(id) ON DELETE CASCADE,
  prev_run_id UUID REFERENCES analysis_runs(id), -- 이전 분석 (비교 기준)

  -- 주간 변화 요약
  period_start TIMESTAMPTZ,              -- 측정 기간 시작
  period_end TIMESTAMPTZ,                -- 측정 기간 끝

  -- 채널별 성과
  channel_deltas JSONB DEFAULT '{}',     -- {youtube: {followers: +500, pct: 3.8}, instagram: {...}}

  -- KPI 달성률
  kpi_progress JSONB DEFAULT '[]',       -- [{metric: "YouTube 구독자", target: 115000, current: 112000, progress_pct: 97.4}]

  -- 콘텐츠 성과 요약
  top_performing_content JSONB DEFAULT '[]',  -- [{title, channel, views, engagement}]
  underperforming_channels TEXT[],            -- 성과 미달 채널 목록

  -- AI 전략 조정 제안
  strategy_suggestions JSONB DEFAULT '[]',    -- [{channel, action: "increase_frequency", reason: "팔로워 증가율 둔화"}]

  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 8. Content Performance (개별 콘텐츠 성과 추적) ───
-- 배포된 콘텐츠의 실제 성과를 추적. 다음 기획에 반영.
CREATE TABLE IF NOT EXISTS content_performance (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  plan_id UUID REFERENCES content_plans(id),

  channel TEXT NOT NULL,                 -- 게시된 채널
  content_type TEXT,                     -- 'video' | 'blog' | 'social' | 'ad'
  title TEXT,                            -- 콘텐츠 제목
  published_at TIMESTAMPTZ,             -- 게시일
  url TEXT,                              -- 콘텐츠 URL

  -- 성과 메트릭
  views INT DEFAULT 0,
  likes INT DEFAULT 0,
  comments INT DEFAULT 0,
  shares INT DEFAULT 0,
  engagement_rate NUMERIC(5,2),          -- (likes+comments+shares)/views * 100

  -- 전환 (추적 가능한 경우)
  clicks INT DEFAULT 0,
  conversions INT DEFAULT 0,             -- 상담 예약 등

  -- AI 평가
  performance_score INT,                 -- 0-100
  performance_label TEXT,                -- 'viral' | 'good' | 'average' | 'underperforming'

  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ─── 9. Strategy Adjustments (전략 조정 히스토리) ───
-- 성과 분석 결과에 따라 자동/수동으로 조정된 전략 기록.
-- "왜 이 전략이 변경됐는지" 근거를 추적.
CREATE TABLE IF NOT EXISTS strategy_adjustments (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  clinic_id UUID NOT NULL REFERENCES clinics(id) ON DELETE CASCADE,
  plan_id UUID REFERENCES content_plans(id),
  performance_id UUID REFERENCES performance_metrics(id), -- 어떤 성과 분석 기반인지

  adjustment_type TEXT NOT NULL,         -- 'frequency_change' | 'pillar_shift' | 'channel_add' | 'channel_pause' | 'content_type_change'
  channel TEXT,                          -- 대상 채널
  description TEXT NOT NULL,             -- "YouTube Shorts 주 3회 → 5회로 증가"
  reason TEXT NOT NULL,                  -- "Shorts 평균 조회수가 Long-form 대비 300% 높음"

  -- 변경 전/후
  before_value JSONB,                    -- {frequency: "주 3회", pillar: "전문성"}
  after_value JSONB,                     -- {frequency: "주 5회", pillar: "전문성+결과"}

  applied_at TIMESTAMPTZ DEFAULT NOW(),
  applied_by TEXT DEFAULT 'system'       -- 'system' | 'user'
);

-- ═══════════════════════════════════════════════════════════════
-- Indexes
-- ═══════════════════════════════════════════════════════════════

-- Clinic lookups
CREATE INDEX IF NOT EXISTS idx_clinics_user ON clinics(user_id);
CREATE INDEX IF NOT EXISTS idx_clinics_url ON clinics(url);
CREATE INDEX IF NOT EXISTS idx_clinics_domain ON clinics(domain);

-- Analysis run history (시간순)
CREATE INDEX IF NOT EXISTS idx_analysis_runs_clinic ON analysis_runs(clinic_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_analysis_runs_status ON analysis_runs(clinic_id, status);

-- Channel snapshots (시계열 쿼리 최적화)
CREATE INDEX IF NOT EXISTS idx_channel_snapshots_clinic_channel ON channel_snapshots(clinic_id, channel, captured_at DESC);
CREATE INDEX IF NOT EXISTS idx_channel_snapshots_run ON channel_snapshots(run_id);

-- Screenshots
CREATE INDEX IF NOT EXISTS idx_screenshots_clinic ON screenshots(clinic_id, run_id);

-- Content plans
CREATE INDEX IF NOT EXISTS idx_content_plans_clinic ON content_plans(clinic_id, is_active);

-- Performance metrics (성과 분석 시계열)
CREATE INDEX IF NOT EXISTS idx_performance_metrics_clinic ON performance_metrics(clinic_id, created_at DESC);

-- Content performance
CREATE INDEX IF NOT EXISTS idx_content_performance_clinic ON content_performance(clinic_id, published_at DESC);
CREATE INDEX IF NOT EXISTS idx_content_performance_channel ON content_performance(clinic_id, channel, published_at DESC);

-- Strategy adjustments
CREATE INDEX IF NOT EXISTS idx_strategy_adjustments_clinic ON strategy_adjustments(clinic_id, applied_at DESC);

-- ═══════════════════════════════════════════════════════════════
-- RLS Policies
-- ═══════════════════════════════════════════════════════════════

ALTER TABLE clinics ENABLE ROW LEVEL SECURITY;
ALTER TABLE analysis_runs ENABLE ROW LEVEL SECURITY;
ALTER TABLE channel_snapshots ENABLE ROW LEVEL SECURITY;
ALTER TABLE screenshots ENABLE ROW LEVEL SECURITY;
ALTER TABLE content_plans ENABLE ROW LEVEL SECURITY;
ALTER TABLE channel_configs ENABLE ROW LEVEL SECURITY;

-- Service role (Edge Functions) — full access
CREATE POLICY "service_all_clinics" ON clinics FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_runs" ON analysis_runs FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_snapshots" ON channel_snapshots FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_screenshots" ON screenshots FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_plans" ON content_plans FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_configs" ON channel_configs FOR ALL USING (auth.role() = 'service_role');

CREATE POLICY "service_all_performance" ON performance_metrics FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_content_perf" ON content_performance FOR ALL USING (auth.role() = 'service_role');
CREATE POLICY "service_all_adjustments" ON strategy_adjustments FOR ALL USING (auth.role() = 'service_role');

ALTER TABLE performance_metrics ENABLE ROW LEVEL SECURITY;
ALTER TABLE content_performance ENABLE ROW LEVEL SECURITY;
ALTER TABLE strategy_adjustments ENABLE ROW LEVEL SECURITY;

-- Anon read (demo mode — 나중에 user_id 기반으로 변경)
CREATE POLICY "anon_read_clinics" ON clinics FOR SELECT USING (true);
CREATE POLICY "anon_read_runs" ON analysis_runs FOR SELECT USING (true);
CREATE POLICY "anon_read_snapshots" ON channel_snapshots FOR SELECT USING (true);
CREATE POLICY "anon_read_screenshots" ON screenshots FOR SELECT USING (true);
CREATE POLICY "anon_read_plans" ON content_plans FOR SELECT USING (true);
CREATE POLICY "anon_read_performance" ON performance_metrics FOR SELECT USING (true);
CREATE POLICY "anon_read_content_perf" ON content_performance FOR SELECT USING (true);
CREATE POLICY "anon_read_adjustments" ON strategy_adjustments FOR SELECT USING (true);

-- ═══════════════════════════════════════════════════════════════
-- Utility Views (트렌드 분석용)
-- ═══════════════════════════════════════════════════════════════

-- 채널별 최신 스냅샷 (현재 상태)
CREATE OR REPLACE VIEW channel_latest AS
SELECT DISTINCT ON (clinic_id, channel)
  clinic_id, channel, handle,
  followers, posts, total_views,
  rating, rating_scale, reviews,
  health_score, health_status,
  screenshot_url, captured_at
FROM channel_snapshots
ORDER BY clinic_id, channel, captured_at DESC;

-- 채널별 주간 변화량
CREATE OR REPLACE VIEW channel_weekly_delta AS
SELECT
  curr.clinic_id,
  curr.channel,
  curr.followers AS current_followers,
  prev.followers AS prev_followers,
  CASE WHEN prev.followers > 0
    THEN ROUND((curr.followers - prev.followers)::NUMERIC / prev.followers * 100, 1)
    ELSE NULL
  END AS followers_change_pct,
  curr.reviews AS current_reviews,
  prev.reviews AS prev_reviews,
  curr.captured_at
FROM channel_latest curr
LEFT JOIN LATERAL (
  SELECT followers, reviews
  FROM channel_snapshots cs
  WHERE cs.clinic_id = curr.clinic_id
    AND cs.channel = curr.channel
    AND cs.captured_at < curr.captured_at - INTERVAL '6 days'
  ORDER BY cs.captured_at DESC
  LIMIT 1
) prev ON true;

-- ═══════════════════════════════════════════════════════════════
-- Backward Compatibility
-- ═══════════════════════════════════════════════════════════════
-- marketing_reports 테이블은 유지 (기존 데이터 + 레거시 API 호환)
-- 새 파이프라인은 clinics + analysis_runs + channel_snapshots 사용
-- 마이그레이션 스크립트로 기존 데이터를 새 테이블로 이관 가능
