"""
실험 ID: 019
실험명: 매출/영업이익/자산 규모 랭크 전수조사

목적:
- KIND 전체 종목의 매출액, 영업이익, 총자산 규모 랭크 산출
- 전체 시장 내 순위 + 섹터 내 순위 동시 확인
- 대형/중형/소형 규모 구간 분류 기준 탐색
- 매출 성장률 랭크도 함께 산출

가설:
1. 매출 기준 상위 10% 종목이 전체 매출의 80% 이상 차지할 것 (멱법칙)
2. 섹터 내 순위가 전체 순위보다 해석에 유의미할 것
3. finance parquet에서 revenue/operating_income/total_assets 가용률 90%+ 예상

방법:
1. 전체 종목 buildAnnual + calcRatios
2. revenueTTM, operatingIncomeTTM, totalAssets 추출
3. 전체 순위 + 섹터 내 순위 계산
4. 규모 구간 분류 (상위 10% 대형, 10~30% 중형, 30~100% 소형)
5. 20종목 샘플 출력

결과 (실험 후 작성):
- 2508종목, 가용률: 매출 87.4% / 영업이익 88.6% / 자산 100% / 3Y성장률 87.4%
- 멱법칙: 매출 상위 10%(219종목)가 전체 매출의 97.8% 차지
- 자산: 상위 10%(250종목)가 전체의 92.1%
- 금융업: 매출(revenue) N/A — 일반 IS 계정 구조 차이
- 이상 데이터: "소프트센" 매출 73조 (1위) — 매핑 오류 의심, 필터링 필요
- 20종목: 전부 매출 기준 "대형" (상위 10%), 섹터 내 순위는 1~5위 수준
- 셀트리온: 전체 153위 / 건강관리 4위 → 섹터 내 순위가 해석에 유의미

결론:
- 가설1 채택: 매출 상위 10%가 97.8% 차지 (80% 예상보다 극단적)
- 가설2 채택: 섹터 내 순위가 절대 순위보다 유의미 (셀트리온 153→4위)
- 가설3 채택: 매출 87.4%, 자산 100% (금융업 매출 제외)
- 규모 구간: 대형 10% / 중형 20% / 소형 70% 자연 분포
- 이상 데이터 필터링 로직 필요 (매출 극단값 감지)
- 랭크 데이터는 JSON 스냅샷으로 캐싱하는 방식 적합 (실시간 2분+ 소요)

실험일: 2026-03-09
"""

import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "src"))

from collections import defaultdict
from pathlib import Path

from dartlab.core.kindList import getKindList
from dartlab.core.dataConfig import DATA_RELEASES
from dartlab.engines.sectorEngine import classify
from dartlab.engines.financeEngine.pivot import buildAnnual
from dartlab.engines.financeEngine.ratios import calcRatios


def _financeExists(stockCode: str) -> bool:
    from dartlab import config
    dataDir = Path(config.dataDir) / DATA_RELEASES["finance"]["dir"]
    return (dataDir / f"{stockCode}.parquet").exists()


TEST_CODES = {
    "005930", "000660", "005380", "005490", "035420", "035720",
    "105560", "055550", "006800", "032830", "051910", "373220",
    "066570", "003550", "000270", "068270", "028260", "096770",
    "034730", "015760",
}


def run():
    kindDf = getKindList()
    codes = kindDf["종목코드"].to_list()
    names = kindDf["회사명"].to_list()
    industries = kindDf["업종"].to_list() if "업종" in kindDf.columns else [None] * len(codes)
    products = kindDf["주요제품"].to_list() if "주요제품" in kindDf.columns else [None] * len(codes)

    records = []
    totalFinance = 0

    print("1단계: 전체 종목 재무 데이터 수집...")
    for i, code in enumerate(codes):
        if i % 500 == 0:
            print(f"  [{i}/{len(codes)}]")

        if not _financeExists(code):
            continue

        aResult = buildAnnual(code)
        if aResult is None:
            continue

        aSeries, _ = aResult
        ratios = calcRatios(aSeries)
        info = classify(names[i], industries[i], products[i])
        totalFinance += 1

        records.append({
            "code": code,
            "name": names[i],
            "sector": info.sector.value,
            "industryGroup": info.industryGroup.value,
            "revenue": ratios.revenueTTM,
            "opIncome": ratios.operatingIncomeTTM,
            "totalAssets": ratios.totalAssets,
            "revenueGrowth3Y": ratios.revenueGrowth3Y,
        })

    print(f"\n수집 완료: {totalFinance}종목")

    hasRevenue = sum(1 for r in records if r["revenue"] is not None and r["revenue"] > 0)
    hasOpIncome = sum(1 for r in records if r["opIncome"] is not None)
    hasAssets = sum(1 for r in records if r["totalAssets"] is not None and r["totalAssets"] > 0)
    hasGrowth = sum(1 for r in records if r["revenueGrowth3Y"] is not None)
    print(f"가용률: 매출 {hasRevenue}({hasRevenue/totalFinance*100:.1f}%) / 영업이익 {hasOpIncome}({hasOpIncome/totalFinance*100:.1f}%) / 자산 {hasAssets}({hasAssets/totalFinance*100:.1f}%) / 3Y성장률 {hasGrowth}({hasGrowth/totalFinance*100:.1f}%)")

    revSorted = sorted(
        [r for r in records if r["revenue"] is not None and r["revenue"] > 0],
        key=lambda x: x["revenue"], reverse=True,
    )
    assetSorted = sorted(
        [r for r in records if r["totalAssets"] is not None and r["totalAssets"] > 0],
        key=lambda x: x["totalAssets"], reverse=True,
    )
    growthSorted = sorted(
        [r for r in records if r["revenueGrowth3Y"] is not None],
        key=lambda x: x["revenueGrowth3Y"], reverse=True,
    )

    for sortedList, label, key in [
        (revSorted, "매출", "revenue"),
        (assetSorted, "자산", "totalAssets"),
    ]:
        n = len(sortedList)
        top10pct = int(n * 0.1)
        totalVal = sum(r[key] for r in sortedList)
        top10val = sum(r[key] for r in sortedList[:top10pct])
        print(f"\n[{label}] 상위 10% ({top10pct}종목)가 전체의 {top10val/totalVal*100:.1f}% 차지")

    revRankMap = {r["code"]: i + 1 for i, r in enumerate(revSorted)}
    assetRankMap = {r["code"]: i + 1 for i, r in enumerate(assetSorted)}
    growthRankMap = {r["code"]: i + 1 for i, r in enumerate(growthSorted)}

    sectorRevLists = defaultdict(list)
    sectorAssetLists = defaultdict(list)
    sectorGrowthLists = defaultdict(list)

    for r in revSorted:
        sectorRevLists[r["sector"]].append(r["code"])
    for r in assetSorted:
        sectorAssetLists[r["sector"]].append(r["code"])
    for r in growthSorted:
        sectorGrowthLists[r["sector"]].append(r["code"])

    sectorRevRank = {}
    for sector, codeList in sectorRevLists.items():
        for i, c in enumerate(codeList):
            sectorRevRank[c] = (i + 1, len(codeList))

    sectorAssetRank = {}
    for sector, codeList in sectorAssetLists.items():
        for i, c in enumerate(codeList):
            sectorAssetRank[c] = (i + 1, len(codeList))

    sectorGrowthRank = {}
    for sector, codeList in sectorGrowthLists.items():
        for i, c in enumerate(codeList):
            sectorGrowthRank[c] = (i + 1, len(codeList))

    nRev = len(revSorted)
    nAsset = len(assetSorted)
    nGrowth = len(growthSorted)

    def _sizeClass(rank, total):
        pct = rank / total
        if pct <= 0.10:
            return "대형"
        if pct <= 0.30:
            return "중형"
        return "소형"

    print(f"\n{'='*120}")
    print("\n[20종목 상세 랭크]")
    header = f"{'종목':<12} {'섹터':<10} {'매출(억)':>10} {'전체':>6} {'섹터내':>8} {'규모':>4} | {'자산(억)':>10} {'전체':>6} {'섹터내':>8} | {'3Y성장':>7} {'전체':>6} {'섹터내':>8}"
    print(header)
    print("-" * len(header))

    recordMap = {r["code"]: r for r in records}
    for code in sorted(TEST_CODES):
        r = recordMap.get(code)
        if r is None:
            continue
        name = r["name"]
        sector = r["sector"]

        rev = r["revenue"]
        revStr = f"{rev/1e8:>10,.0f}" if rev else "      N/A"
        revRk = revRankMap.get(code)
        revRkStr = f"{revRk}/{nRev}" if revRk else "N/A"
        secRevRk = sectorRevRank.get(code)
        secRevRkStr = f"{secRevRk[0]}/{secRevRk[1]}" if secRevRk else "N/A"
        sizeStr = _sizeClass(revRk, nRev) if revRk else "N/A"

        assets = r["totalAssets"]
        assetStr = f"{assets/1e8:>10,.0f}" if assets else "      N/A"
        assetRk = assetRankMap.get(code)
        assetRkStr = f"{assetRk}/{nAsset}" if assetRk else "N/A"
        secAssetRk = sectorAssetRank.get(code)
        secAssetRkStr = f"{secAssetRk[0]}/{secAssetRk[1]}" if secAssetRk else "N/A"

        growth = r["revenueGrowth3Y"]
        growthStr = f"{growth:>7.1f}%" if growth is not None else "    N/A"
        growthRk = growthRankMap.get(code)
        growthRkStr = f"{growthRk}/{nGrowth}" if growthRk else "N/A"
        secGrowthRk = sectorGrowthRank.get(code)
        secGrowthRkStr = f"{secGrowthRk[0]}/{secGrowthRk[1]}" if secGrowthRk else "N/A"

        print(f"{name:<12} {sector:<10} {revStr} {revRkStr:>6} {secRevRkStr:>8} {sizeStr:>4} | {assetStr} {assetRkStr:>6} {secAssetRkStr:>8} | {growthStr} {growthRkStr:>6} {secGrowthRkStr:>8}")

    print(f"\n{'='*120}")
    print("\n[규모 구간 분포]")
    sizeCount = {"대형": 0, "중형": 0, "소형": 0}
    for i, r in enumerate(revSorted):
        sc = _sizeClass(i + 1, nRev)
        sizeCount[sc] += 1
    for sc, cnt in sizeCount.items():
        print(f"  {sc}: {cnt}종목 ({cnt/nRev*100:.1f}%)")

    print(f"\n[섹터별 종목 수 (매출 기준)]")
    for sector in sorted(sectorRevLists.keys()):
        n = len(sectorRevLists[sector])
        print(f"  {sector:<15} {n:>4}종목")

    print(f"\n[매출 상위 20]")
    for i, r in enumerate(revSorted[:20]):
        print(f"  {i+1:>3}. {r['name']:<15} {r['sector']:<10} {r['revenue']/1e8:>12,.0f}억")

    print(f"\n[매출 성장률 상위 20 (3Y CAGR)]")
    for i, r in enumerate(growthSorted[:20]):
        print(f"  {i+1:>3}. {r['name']:<15} {r['sector']:<10} {r['revenueGrowth3Y']:>7.1f}%")


if __name__ == "__main__":
    run()
