"""Coffee C (KC=F) futures price extraction.

Downloads daily OHLCV data from Yahoo Finance via yfinance and stores as
gzip CSV in the landing directory. Uses SHA256 of CSV bytes as the
idempotency key — skips if a file with the same hash already exists.

Landing path: LANDING_DIR/prices/coffee_kc/{hash8}.csv.gzip
"""

import gzip
import io
import logging
import os
import sys
from pathlib import Path

import yfinance as yf
from extract_core import (
    content_hash,
    end_run,
    landing_path,
    open_state_db,
    start_run,
    write_bytes_atomic,
)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    handlers=[logging.StreamHandler(sys.stdout)],
)
logger = logging.getLogger("Coffee Prices Extractor")

LANDING_DIR = Path(os.getenv("LANDING_DIR", "data/landing"))
TICKER = "KC=F"
DEST_SUBDIR = "prices/coffee_kc"

# yfinance raises on network issues; give it enough time for the full history
DOWNLOAD_TIMEOUT_SECONDS = 120


def extract_coffee_prices() -> None:
    """Download KC=F daily OHLCV history and store as gzip CSV.

    Idempotent: computes SHA256 of CSV bytes, skips if already on disk.
    On first run downloads full history (period='max'). On subsequent runs
    the hash matches if no new trading days have closed since last run.
    """
    conn = open_state_db(LANDING_DIR)
    run_id = start_run(conn, "coffee_prices")
    try:
        logger.info(f"Downloading {TICKER} daily OHLCV from Yahoo Finance...")

        ticker = yf.Ticker(TICKER)
        df = ticker.history(period="max", interval="1d", auto_adjust=False, timeout=DOWNLOAD_TIMEOUT_SECONDS)

        assert df is not None and len(df) > 0, f"yfinance returned empty DataFrame for {TICKER}"

        # Reset index so Date becomes a plain column
        df = df.reset_index()

        # Keep standard OHLCV columns only; yfinance may return extra columns
        keep_cols = [c for c in ["Date", "Open", "High", "Low", "Close", "Adj Close", "Volume"] if c in df.columns]
        df = df[keep_cols]

        # Normalize Date to ISO string for CSV stability across timezones
        df["Date"] = df["Date"].dt.strftime("%Y-%m-%d")

        # Serialize to CSV bytes
        csv_buf = io.StringIO()
        df.to_csv(csv_buf, index=False)
        csv_bytes = csv_buf.getvalue().encode("utf-8")

        assert len(csv_bytes) > 0, "CSV serialization produced empty output"

        etag = content_hash(csv_bytes)
        dest_dir = landing_path(LANDING_DIR, DEST_SUBDIR)
        local_file = dest_dir / f"{etag}.csv.gzip"

        if local_file.exists():
            logger.info(f"File {local_file.name} already exists — no new data, skipping")
            end_run(conn, run_id, status="success", files_skipped=1)
            return

        compressed = gzip.compress(csv_bytes)
        bytes_written = write_bytes_atomic(local_file, compressed)

        logger.info(
            f"Stored {local_file} ({bytes_written:,} bytes, {len(df):,} rows)"
        )
        end_run(conn, run_id, status="success", files_written=1, bytes_written=bytes_written)
    except Exception as e:
        end_run(conn, run_id, status="failed", error_message=str(e))
        raise
    finally:
        conn.close()


if __name__ == "__main__":
    extract_coffee_prices()
