"""
경비 부적정 사용 탐지 스크립트
- 법인카드 사용내역 CSV 파일을 분석하여 부적정 사용 패턴을 탐지합니다.
- ChatGPT와 토론하여 도출한 탐지 논리를 코드로 구현한 결과물입니다.
"""

import sys
import io
import os

import pandas as pd
from datetime import datetime, timedelta

# ========================================
# 출력 설정: 콘솔 + 파일 동시 저장
# ========================================
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
OUTPUT_PATH = os.path.join(BASE_DIR, "경비부적정_탐지결과.txt")

class TeeWriter:
    def __init__(self, file, stdout):
        self.file = file
        self.stdout = stdout
    def write(self, text):
        self.stdout.write(text)
        self.file.write(text)
    def flush(self):
        self.stdout.flush()
        self.file.flush()

_original_stdout = sys.stdout
try:
    _original_stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
except:
    pass
_output_file = open(OUTPUT_PATH, 'w', encoding='utf-8')
sys.stdout = TeeWriter(_output_file, _original_stdout)

# ========================================
# 데이터 로드
# ========================================
df = pd.read_csv(os.path.join(BASE_DIR, "법인카드_사용내역.csv"), encoding="utf-8-sig")
df["사용일시"] = pd.to_datetime(df["사용일시"])
df["사용일자"] = df["사용일시"].dt.date
df["사용시간"] = df["사용일시"].dt.hour
df["요일"] = df["사용일시"].dt.dayofweek  # 0=월, 6=일

# 주소에서 '구' 추출
df["사용처_구"] = df["사용처주소"].str.extract(r"(\S+구)")
df["자택_구"] = df["사용자자택주소"].str.extract(r"(\S+구)")

# 주소에서 '동' 추출
df["사용처_동"] = df["사용처주소"].str.extract(r"(\S+동)")
df["자택_동"] = df["사용자자택주소"].str.extract(r"(\S+동)")

print("=" * 80)
print("법인카드 부적정 사용 탐지 분석 보고서")
print("=" * 80)
print(f"분석 대상 기간: {df['사용일자'].min()} ~ {df['사용일자'].max()}")
print(f"총 사용 건수: {len(df)}건")
print(f"총 사용 금액: {df['금액'].sum():,.0f}원")
print()

# ========================================
# 탐지 1: 자택 근처 법인카드 사용 (사적 사용 의심)
# ========================================
print("■ 탐지 1: 자택 근처 법인카드 사용 (사적 사용 의심)")
print("-" * 60)

# 사용처 주소의 '구'와 자택 주소의 '구'가 동일한 건
home_nearby = df[df["사용처_구"] == df["자택_구"]].copy()

# 의심도 점수 부여
home_nearby["의심점수"] = 0
home_nearby.loc[home_nearby["사용처_동"] == home_nearby["자택_동"], "의심점수"] += 2  # 동까지 일치
home_nearby.loc[home_nearby["사용시간"] >= 18, "의심점수"] += 2  # 퇴근 후
home_nearby.loc[home_nearby["요일"] >= 5, "의심점수"] += 3  # 주말
home_nearby.loc[home_nearby["업종"].isin(["주류", "카페", "치킨"]), "의심점수"] += 1  # 업무 관련성 낮은 업종

# 사용자별 집계
home_summary = home_nearby.groupby("사용자").agg(
    건수=("번호", "count"),
    총금액=("금액", "sum"),
    평균의심점수=("의심점수", "mean"),
    주요업종=("업종", lambda x: ", ".join(x.unique())),
    주요사용처=("사용처", lambda x: ", ".join(x.unique())),
).sort_values("평균의심점수", ascending=False)

print(f"\n자택 근처 사용 건수: {len(home_nearby)}건 / 전체 {len(df)}건 ({len(home_nearby)/len(df)*100:.1f}%)")
print(f"\n[사용자별 현황]")
for idx, row in home_summary.iterrows():
    print(f"  - {idx}: {row['건수']}건, {row['총금액']:,.0f}원, 의심점수 {row['평균의심점수']:.1f}, 업종: {row['주요업종']}")

# 상세 의심 건
high_risk_home = home_nearby[home_nearby["의심점수"] >= 3].sort_values("의심점수", ascending=False)
if len(high_risk_home) > 0:
    print(f"\n[고위험 건 상세 ({len(high_risk_home)}건)]")
    for _, row in high_risk_home.iterrows():
        print(f"  #{row['번호']:3d} | {row['사용일시']} | {row['사용자']} | {row['사용처']} ({row['업종']}) | {row['금액']:,.0f}원 | 의심점수: {row['의심점수']}")

print()

# ========================================
# 탐지 2: 분할 결제 의심
# ========================================
print("■ 탐지 2: 분할 결제 의심")
print("-" * 60)

split_suspects = []

# 동일 날짜 + 동일 사용자 + 동일 사용처 그룹핑
for (date, user, store), group in df.groupby(["사용일자", "사용자", "사용처"]):
    if len(group) >= 2:
        # 결제 시간 간격 확인
        times = group["사용일시"].sort_values()
        time_diff = (times.max() - times.min()).total_seconds() / 60  # 분

        if time_diff <= 60:  # 60분 이내
            total = group["금액"].sum()
            split_suspects.append({
                "사용일자": date,
                "사용자": user,
                "사용처": store,
                "건수": len(group),
                "개별금액": list(group["금액"].values),
                "합계금액": total,
                "시간간격(분)": time_diff,
                "번호목록": list(group["번호"].values),
            })

print(f"\n분할 결제 의심 건: {len(split_suspects)}건")
if split_suspects:
    print(f"\n[상세 내역]")
    for s in split_suspects:
        amounts = " + ".join([f"{a:,.0f}" for a in s["개별금액"]])
        flag = " ★ 합산 시 기준 초과" if s["합계금액"] > 300000 else ""
        print(f"  - {s['사용일자']} | {s['사용자']} | {s['사용처']} | {s['건수']}건")
        print(f"    금액: {amounts} = {s['합계금액']:,.0f}원 (간격: {s['시간간격(분)']:.0f}분){flag}")

print()

# ========================================
# 탐지 3: 동일 점포 반복 사용
# ========================================
print("■ 탐지 3: 동일 점포 반복 사용")
print("-" * 60)

repeat_usage = df.groupby(["사용자", "사용처"]).agg(
    사용횟수=("번호", "count"),
    총금액=("금액", "sum"),
    업종=("업종", "first"),
    사용처주소=("사용처주소", "first"),
    자택주소=("사용자자택주소", "first"),
).reset_index()

# 3회 이상 반복 사용
repeat_high = repeat_usage[repeat_usage["사용횟수"] >= 3].sort_values(
    "사용횟수", ascending=False
)

print(f"\n동일 점포 3회 이상 반복 사용: {len(repeat_high)}건")
if len(repeat_high) > 0:
    print(f"\n[상세 내역]")
    for _, row in repeat_high.iterrows():
        # 자택 근처 여부 확인
        home_flag = ""
        if pd.notna(row["사용처주소"]) and pd.notna(row["자택주소"]):
            사용처구 = row["사용처주소"].split("구")[0].split()[-1] + "구" if "구" in row["사용처주소"] else ""
            자택구 = row["자택주소"].split("구")[0].split()[-1] + "구" if "구" in row["자택주소"] else ""
            if 사용처구 == 자택구:
                home_flag = " [자택근처]"

        # 주류 업종 표시
        liquor_flag = " [주류업종]" if row["업종"] in ["주류"] else ""

        print(f"  - {row['사용자']} → {row['사용처']} ({row['업종']}): {row['사용횟수']}회, {row['총금액']:,.0f}원{home_flag}{liquor_flag}")

print()

# ========================================
# 탐지 4: 사업비 기준 위반
# ========================================
print("■ 탐지 4: 사업비 기준 위반")
print("-" * 60)

# 기준 설정
LUNCH_LIMIT_PER_PERSON = 15000  # 1인당 점심식대 한도
ENTERTAINMENT_LIMIT = 300000     # 건당 접대비 한도

# 4-1: 점심식대 한도 초과 (1인당)
lunch = df[df["사용목적"] == "점심식사"].copy()
lunch["1인당금액"] = lunch["금액"] / lunch["참석인원"]
lunch_over = lunch[lunch["1인당금액"] > LUNCH_LIMIT_PER_PERSON]

print(f"\n[점심식대 1인당 한도 초과] (기준: {LUNCH_LIMIT_PER_PERSON:,.0f}원/인)")
print(f"  위반 건수: {len(lunch_over)}건")
if len(lunch_over) > 0:
    for _, row in lunch_over.iterrows():
        per_person = row["1인당금액"]
        over = per_person - LUNCH_LIMIT_PER_PERSON
        print(f"  #{row['번호']:3d} | {row['사용일시'].date()} | {row['사용자']} | {row['사용처']} | {row['금액']:,.0f}원/{row['참석인원']}명 = {per_person:,.0f}원/인 (초과: {over:,.0f}원)")

# 4-2: 접대비 한도 초과
entertainment = df[df["사용목적"].isin(["고객접대", "고객미팅"])]
ent_over = entertainment[entertainment["금액"] > ENTERTAINMENT_LIMIT]

print(f"\n[접대비 건당 한도 초과] (기준: {ENTERTAINMENT_LIMIT:,.0f}원/건)")
print(f"  위반 건수: {len(ent_over)}건")
if len(ent_over) > 0:
    for _, row in ent_over.iterrows():
        over = row["금액"] - ENTERTAINMENT_LIMIT
        print(f"  #{row['번호']:3d} | {row['사용일시'].date()} | {row['사용자']} | {row['사용처']} | {row['금액']:,.0f}원 (초과: {over:,.0f}원)")

# 4-3: 주류 업종 사용 건 (사전 승인 필요)
liquor = df[df["업종"] == "주류"]
print(f"\n[주류 업종 사용] (사전 승인 필요)")
print(f"  총 건수: {len(liquor)}건, 총 금액: {liquor['금액'].sum():,.0f}원")
liquor_by_user = liquor.groupby("사용자").agg(건수=("번호", "count"), 총금액=("금액", "sum"))
for idx, row in liquor_by_user.iterrows():
    print(f"  - {idx}: {row['건수']}건, {row['총금액']:,.0f}원")

print()

# ========================================
# 종합 요약
# ========================================
print("=" * 80)
print("종합 분석 요약")
print("=" * 80)

print("""
[주요 의심자 프로필]

1. 이정호 (마케팅팀)
   - 자택(마포구 연남동) 근처 주류 업종 집중 사용
   - 호프하우스 반복 사용 (10회 이상)
   - 퇴근 이후/주말 사용 다수
   → 사적 사용 가능성 높음, 주류 사용 사전승인 여부 확인 필요

2. 김민수 (영업지원팀)
   - 분할 결제 반복 패턴 (강남BBQ, 역삼스테이크)
   - 합산 시 건당 접대비 한도(30만원) 초과
   → 한도 회피 목적의 분할 결제 의심

3. 최영진 (총무팀)
   - 자택(관악구 봉천동) 근처 집중 사용
   - 분할 결제 패턴 (관악갈비, 봉천횟집)
   → 사적 사용 및 분할 결제 복합 의심

4. 정다영 (인사팀)
   - 자택(노원구 상계동) 근처 사용 다수
   - 분할 결제 패턴 (노원삼겹살, 노원치킨)
   → 사적 사용 및 분할 결제 복합 의심

5. 한승우 (영업팀)
   - 자택(영등포구 당산동) 근처 주류 업종 사용
   - 분할 결제 패턴 (당산포차, 당산횟집)
   → 사적 사용 및 분할 결제 복합 의심
""")

print("분석 완료.")

# 파일 저장 완료
_output_file.close()
sys.stdout = _original_stdout
print(f"\n결과가 저장되었습니다: {OUTPUT_PATH}")
