"""init_assessment tool -- sets up the upgrade assessment project.

This is called after License Portal discovery (connect_lma,
find_customer, get_customer_licenses) to set up the assessment project. It:
1. Validates prerequisites (sf CLI, git, GitHub access)
2. Creates the SFDX project via sf CLI (never hand-builds)
3. Creates assessment-specific directories (manifest/, package-repos/, analysis/)
4. Checks org authorization or lists available orgs
5. Hard-blocks production orgs (sandbox only for metadata retrieval)
6. Creates/updates the state file for resume capability (preserves license data)
7. Detects previous assessments and stale data

If License Portal discovery has already been run, the tool reads
customer info and package data from state. org_alias is optional at
this point -- the user provides it when ready for metadata retrieval.

If skip_sandbox is True, the tool skips org authorization entirely
and enters portal-only mode: the assessment proceeds using only
production license data as the package baseline (no metadata retrieval).
"""

import logging
from pathlib import Path
from typing import Any

from ..utils import sf_cli, git_cli, state, paths

logger = logging.getLogger(__name__)

TOOL_DEFINITION = {
    "name": "init_assessment",
    "description": (
        "Initialize a CloudSense upgrade assessment project. "
        "Creates the SFDX project structure, validates prerequisites "
        "(Salesforce CLI, GitHub access), checks org authorization, "
        "and sets up the assessment directory layout. "
        "Call connect_lma, find_customer, and get_customer_licenses first "
        "to identify the customer and their packages via the License Portal. "
        "The customer org alias is optional -- provide it when ready "
        "for metadata retrieval (must be a SANDBOX, not production). "
        "If skip_sandbox is true, the tool enters portal-only mode and "
        "skips org authorization entirely. "
        "Returns a structured report of what was set up and what needs attention."
    ),
    "inputSchema": {
        "type": "object",
        "properties": {
            "customer_name": {
                "type": "string",
                "description": (
                    "Customer name for the assessment. Used as the SFDX project "
                    "directory name. Example: 'nbnco', 'maxis', 'starhub'. "
                    "Use lowercase with no spaces. If omitted, reads from "
                    "state (set by find_customer)."
                ),
            },
            "target_version": {
                "type": "string",
                "description": (
                    "Target CloudSense release version to upgrade to. "
                    "Examples: 'R38', 'R39', 'R40'. "
                    "This determines which package version tags to check out. "
                    "If omitted, must be provided later."
                ),
            },
            "org_alias": {
                "type": "string",
                "description": (
                    "Salesforce sandbox org alias to use. If provided, the tool "
                    "validates this org is authorized and is a sandbox. "
                    "If not provided, the tool lists all authorized orgs "
                    "so the user can choose. "
                    "Example: 'nbnpsup', 'maxis-dev'"
                ),
            },
            "instance_url": {
                "type": "string",
                "description": (
                    "Salesforce instance URL for org login. Only needed if the org "
                    "is not yet authorized. "
                    "Example: 'https://nbn--psup.sandbox.my.salesforce.com/'"
                ),
            },
            "skip_sandbox": {
                "type": "boolean",
                "description": (
                    "If true, skip org authorization entirely and proceed in "
                    "portal-only mode. Use this when no sandbox is available. "
                    "The assessment will use production license data as the "
                    "package baseline."
                ),
            },
            "working_directory": {
                "type": "string",
                "description": (
                    "Workspace directory for state and output files. "
                    "The AI passes this automatically."
                ),
            },
        },
        "required": [],
    },
}


async def run(arguments: dict[str, Any]) -> str:
    """Execute the init_assessment tool."""
    state.set_working_dir(arguments.get("working_directory"))
    existing_state = state.load_state()

    customer = arguments.get("customer_name")
    if not customer and existing_state:
        acct_name = existing_state.get("lma_customer_account_name", "")
        if acct_name:
            customer = acct_name.lower().replace(" ", "").replace(".", "")
    if not customer:
        return (
            "## STATUS: INCOMPLETE\n\n"
            "customer_name is required. Either provide it directly or "
            "call find_customer first so the tool can read it from state."
        )

    target_version = arguments.get("target_version", "")
    if not target_version and existing_state:
        target_version = existing_state.get("target_version", "")

    working_dir = state.get_working_dir()
    org_alias = arguments.get("org_alias")
    instance_url = arguments.get("instance_url")
    skip_sandbox = arguments.get("skip_sandbox", False)

    report_sections: list[str] = []
    warnings: list[str] = []
    blockers: list[str] = []

    # ── 1. Validate prerequisites ──────────────────────────────────
    report_sections.append("## Prerequisite Checks\n")

    sf_info = sf_cli.check_sf_installed()
    if sf_info["installed"]:
        report_sections.append(f"- Salesforce CLI: INSTALLED ({sf_info['version']})")
    else:
        blockers.append(
            "Salesforce CLI (sf) is NOT installed. "
            "Install from https://developer.salesforce.com/tools/salesforcecli"
        )
        report_sections.append("- Salesforce CLI: NOT INSTALLED (BLOCKER)")

    git_info = git_cli.check_git_installed()
    if git_info["installed"]:
        report_sections.append(f"- Git: INSTALLED ({git_info['version']})")
    else:
        blockers.append(
            "Git is NOT installed. "
            "Install from https://git-scm.com/downloads"
        )
        report_sections.append("- Git: NOT INSTALLED (BLOCKER)")

    gh_info = git_cli.check_github_access()
    if gh_info["authenticated"]:
        report_sections.append(
            f"- GitHub access: AUTHENTICATED via {gh_info['method']}"
            + (f" (user: {gh_info['username']})" if gh_info["username"] else "")
        )
    else:
        blockers.append(gh_info["message"])
        report_sections.append(f"- GitHub access: NOT AUTHENTICATED (BLOCKER)")

    if blockers:
        report_sections.append("\n## BLOCKERS - Cannot proceed\n")
        for b in blockers:
            report_sections.append(f"- {b}")
        report_sections.append(
            "\nResolve these blockers and call init_assessment again."
        )
        return "\n".join(report_sections)

    # ── 2. Check for previous assessment ───────────────────────────
    report_sections.append("")
    if existing_state:
        prev_customer = existing_state.get("customer", "unknown")
        prev_version = existing_state.get("target_version", "unknown")
        prev_steps = existing_state.get("completed_steps", [])
        report_sections.append("## Previous Assessment Detected\n")
        report_sections.append(f"- Customer: {prev_customer}")
        report_sections.append(f"- Target version: {prev_version}")
        report_sections.append(f"- Completed steps: {', '.join(prev_steps) or 'none'}")
        report_sections.append(f"- Started: {existing_state.get('started_at', 'unknown')}")

        if prev_customer == customer and prev_version == target_version:
            report_sections.append(
                "\nSame customer and version. The tool will resume from "
                "where the previous assessment left off. Already-completed "
                "steps will be skipped."
            )
        else:
            report_sections.append(
                f"\nDifferent assessment ({prev_customer}/{prev_version} vs "
                f"{customer}/{target_version}). Starting fresh -- the previous "
                f"state file will be overwritten."
            )

    # ── 2b. Read license data from state (if available) ────────────
    lma_data = None
    if existing_state:
        lma_data = existing_state.get("lma_customer_data")
        if lma_data:
            report_sections.append("\n## Customer License Data (from prior discovery)\n")
            report_sections.append(f"- Customer: {lma_data.get('account_name', '?')}")
            report_sections.append(
                f"- Health Score: {lma_data.get('health_score', '?')}/100 "
                f"({lma_data.get('health_label', '?')})"
            )
            report_sections.append(
                f"- Production packages: {lma_data.get('production_license_count', '?')}"
            )
            org_info_lma = lma_data.get("org_summary", {})
            rec_sandbox = org_info_lma.get("recommended_sandbox")
            if rec_sandbox:
                report_sections.append(
                    f"- Recommended sandbox: {rec_sandbox}"
                )

    # ── 3. Create SFDX project ─────────────────────────────────────
    report_sections.append("\n## Project Setup\n")
    project_dir = working_dir / customer

    if project_dir.exists() and (project_dir / "sfdx-project.json").exists():
        report_sections.append(
            f"- SFDX project already exists at: {project_dir}"
        )
    else:
        if not sf_info["installed"]:
            report_sections.append("- SKIPPED: sf CLI not available")
        else:
            try:
                paths.ensure_dir(working_dir)
                sf_cli.generate_project(customer, cwd=working_dir)
                report_sections.append(
                    f"- Created SFDX project: {project_dir}"
                )
            except sf_cli.SfCliError as e:
                blockers.append(f"Failed to create SFDX project: {e}")
                report_sections.append(f"- FAILED to create SFDX project: {e}")

    # ── 4. Create assessment directories ───────────────────────────
    dirs = paths.assessment_dirs(working_dir)
    proj = paths.project_dirs(working_dir, customer)

    for name, dir_path in {**dirs, "manifest": proj["manifest"]}.items():
        if name == "working_dir":
            continue
        paths.ensure_dir(dir_path)

    report_sections.append(f"- Assessment directories created:")
    report_sections.append(f"  - {dirs['package_repos']} (from/to version repos)")
    report_sections.append(f"  - {dirs['analysis']} (analysis output)")
    report_sections.append(f"  - {proj['manifest']} (package.xml files)")

    # ── 5. Org authorization ───────────────────────────────────────
    report_sections.append("\n## Org Authorization\n")

    if skip_sandbox:
        report_sections.append(
            "- **Portal-only mode**: sandbox authorization skipped.\n"
            "- The assessment will use production license data as the "
            "package baseline. Metadata retrieval steps will be skipped."
        )
        assessment_mode = "lma_only"
    elif org_alias:
        try:
            org_data = sf_cli.display_org(org_alias, cwd=project_dir)
            org_result = org_data.get("result", {})
            is_sandbox = org_result.get("isSandbox", None)
            org_id = org_result.get("id", "unknown")
            username = org_result.get("username", "unknown")
            instance = org_result.get("instanceUrl", "unknown")
            api_version = org_result.get("apiVersion", "unknown")

            report_sections.append(f"- Org alias: {org_alias}")
            report_sections.append(f"- Username: {username}")
            report_sections.append(f"- Org ID: {org_id}")
            report_sections.append(f"- Instance: {instance}")
            report_sections.append(f"- API version: {api_version}")

            if is_sandbox is True:
                report_sections.append(f"- Type: SANDBOX (safe for assessment)")
            elif is_sandbox is False:
                blockers.append(
                    "PRODUCTION ORG DETECTED. Customer metadata retrieval "
                    "must ALWAYS target a sandbox org, never production. "
                    "Please authorize a sandbox org instead. "
                    "Use the sandbox recommended by get_customer_licenses "
                    "if available."
                )
                report_sections.append(
                    f"- Type: PRODUCTION (BLOCKER: must use a sandbox)"
                )
            else:
                report_sections.append(f"- Type: Unknown")

        except sf_cli.SfCliError:
            report_sections.append(
                f"- Org '{org_alias}' is NOT authorized."
            )
            if instance_url:
                report_sections.append(
                    f"- To authorize, the user must run:\n"
                    f"  sf org login web --alias {org_alias} "
                    f"--instance-url {instance_url}\n"
                    f"  This will open a browser for Salesforce login."
                )
            else:
                report_sections.append(
                    f"- To authorize, the user needs the Salesforce instance URL.\n"
                    f"  Then run: sf org login web --alias {org_alias} "
                    f"--instance-url <URL>\n"
                    f"  Ask the user for the instance URL "
                    f"(e.g., https://customer--sandbox.sandbox.my.salesforce.com/)"
                )
            blockers.append(f"Org '{org_alias}' is not authorized.")
    else:
        try:
            orgs = sf_cli.list_orgs(cwd=project_dir)
            if orgs:
                report_sections.append("- No org alias provided. Available orgs:\n")
                for org in orgs:
                    alias = org.get("alias", "no-alias")
                    username = org.get("username", "unknown")
                    instance = org.get("instanceUrl", "unknown")
                    connected = org.get("connectedStatus", "unknown")
                    report_sections.append(
                        f"  - {alias}: {username} ({instance}) [{connected}]"
                    )
                report_sections.append(
                    "\n  Ask the user which org to use for this assessment, "
                    "then call init_assessment again with the org_alias parameter."
                )
            else:
                report_sections.append(
                    "- No authorized orgs found. The user needs to authorize an org.\n"
                    "  They need the Salesforce instance URL, then run:\n"
                    "  sf org login web --alias <alias> --instance-url <URL>\n"
                    "  Ask the user for the customer's Salesforce org details."
                )
            blockers.append("No org alias specified -- user must choose an org.")
        except sf_cli.SfCliError as e:
            report_sections.append(f"- Failed to list orgs: {e}")
            blockers.append(f"Failed to list orgs: {e}")

    # ── 6. Create/update state file ────────────────────────────────
    if not blockers:
        state_updates: dict[str, Any] = {
            "customer": customer,
            "org_alias": org_alias or "",
        }
        if target_version:
            state_updates["target_version"] = target_version
        if skip_sandbox:
            state_updates["assessment_mode"] = "lma_only"

        state.ensure_state(**state_updates)
        state.create_state(working_dir, customer, target_version or "", org_alias or "")
        state.mark_step_completed(step="init")
        report_sections.append("\n## State\n")
        report_sections.append("- State file updated: upgrade-assessment-state.json")
        report_sections.append("- Step 'init' marked as completed")
        if lma_data:
            report_sections.append("- Customer license data preserved in state")
        if skip_sandbox:
            report_sections.append("- assessment_mode = lma_only")

    # ── 7. Summary ─────────────────────────────────────────────────
    report_sections.append("\n---\n")
    if blockers:
        report_sections.append("## STATUS: INCOMPLETE - Action Required\n")
        for b in blockers:
            report_sections.append(f"- {b}")
    else:
        report_sections.append("## STATUS: READY\n")
        report_sections.append(
            f"Assessment initialized for {customer} -> {target_version}.\n"
            f"Next step: call get_installed_packages to discover "
            f"CloudSense packages in the org."
        )

    if warnings:
        report_sections.append("\n## Warnings\n")
        for w in warnings:
            report_sections.append(f"- {w}")

    return "\n".join(report_sections)
