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

This is called after LMA 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 the state file for resume capability (preserves LMA data)
7. Detects previous assessments and stale data

If LMA 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.
"""

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 LMA. "
        "The customer org alias is optional -- provide it when ready "
        "for metadata retrieval (must be a SANDBOX, not production). "
        "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."
                ),
            },
            "working_directory": {
                "type": "string",
                "description": (
                    "Absolute path to the directory where the assessment project "
                    "will be created. The SFDX project and all analysis outputs "
                    "will be placed here. Example: '/Users/john/Desktop/assessments'"
                ),
            },
            "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."
                ),
            },
            "org_alias": {
                "type": "string",
                "description": (
                    "Salesforce org alias to use. If provided, the tool validates "
                    "this org is authorized. 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/'"
                ),
            },
        },
        "required": ["customer_name", "working_directory", "target_version"],
    },
}


async def run(arguments: dict[str, Any]) -> str:
    """Execute the init_assessment tool."""
    customer = arguments["customer_name"]
    working_dir = Path(arguments["working_directory"])
    target_version = arguments["target_version"]
    org_alias = arguments.get("org_alias")
    instance_url = arguments.get("instance_url")

    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("")
    existing_state = state.load_state(working_dir)
    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 LMA 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## LMA Customer 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 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:
        if existing_state and lma_data:
            state.update_state(
                working_dir,
                customer=customer,
                target_version=target_version,
                org_alias=org_alias or "",
            )
        else:
            state.create_state(
                working_dir,
                customer=customer,
                target_version=target_version,
                org_alias=org_alias or "",
            )
        state.mark_step_completed(working_dir, "init")
        report_sections.append("\n## State\n")
        report_sections.append("- State file created: upgrade-assessment-state.json")
        report_sections.append("- Step 'init' marked as completed")
        if lma_data:
            report_sections.append("- LMA customer data preserved in state")

    # ── 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)
