#!/usr/bin/env bash
set -euo pipefail
#
# 14-dev-flow.sh — Professional Development Flow (FLAGSHIP)
#
# Description:
#   The complete PR-first, professional development workflow. Guides developers
#   through the full lifecycle: branch creation, draft PR, iterative development
#   with security scanning, review preparation, and clean merge with branch
#   cleanup. Platform-agnostic (GitHub, GitLab, or standalone).
#
# Usage:
#   ./14-dev-flow.sh                   # Interactive menu
#   ./14-dev-flow.sh start             # Start a new feature
#   ./14-dev-flow.sh develop           # Development cycle
#   ./14-dev-flow.sh review            # Prepare for review
#   ./14-dev-flow.sh merge             # Merge and cleanup
#   ./14-dev-flow.sh status            # Show current flow status
#
# Dependencies:
#   securegit, gh (optional), glab (optional)
#

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/lib/securegit-common.sh"

# ─── Constants ───────────────────────────────────────────────────────────────
readonly PROG_NAME="dev-flow"
readonly VERSION="1.0.0"

# ─── Platform detection ─────────────────────────────────────────────────────

_detect_platform() {
    if command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
        echo "github"
    elif command -v glab &>/dev/null && glab auth status &>/dev/null 2>&1; then
        echo "gitlab"
    else
        echo "standalone"
    fi
}

_platform_name() {
    case "$(_detect_platform)" in
        github)     echo "GitHub" ;;
        gitlab)     echo "GitLab" ;;
        standalone) echo "Standalone (no CLI)" ;;
    esac
}

# ─── Branch name builder ────────────────────────────────────────────────────

_build_branch_name() {
    local prefix description ticket branch_name

    sg_header "Create Feature Branch"

    sg_info "Available prefixes:"
    local prefixes
    prefixes="$(sg_branch_prefixes)"
    local prefix_arr; read -ra prefix_arr <<< "$prefixes"
    local i
    for i in "${!prefix_arr[@]}"; do
        printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((i + 1))" "${prefix_arr[$i]}"
    done
    echo

    local prefix_choice
    while true; do
        printf "Select prefix [1-%d]: " "${#prefix_arr[@]}"
        read -r prefix_choice
        if [[ "$prefix_choice" =~ ^[0-9]+$ ]] && (( prefix_choice >= 1 && prefix_choice <= ${#prefix_arr[@]} )); then
            prefix="${prefix_arr[$((prefix_choice - 1))]}"
            break
        fi
        sg_warn "Invalid selection."
    done

    description=$(sg_prompt "Short description (e.g., add-user-auth)")
    description=$(echo "$description" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')

    if [[ "${SG_REQUIRE_TICKET:-false}" == "true" ]]; then
        ticket=$(sg_prompt "Ticket reference (e.g., PROJ-123)" "")
        if [[ -n "$ticket" ]]; then
            branch_name="$prefix/$ticket-$description"
        else
            sg_warn "Ticket reference is required by project config."
            ticket=$(sg_prompt "Ticket reference")
            branch_name="$prefix/$ticket-$description"
        fi
    else
        ticket=$(sg_prompt "Ticket reference (optional, press Enter to skip)" "")
        if [[ -n "$ticket" ]]; then
            branch_name="$prefix/$ticket-$description"
        else
            branch_name="$prefix/$description"
        fi
    fi

    echo "$branch_name"
}

# ─── Conventional commit builder ────────────────────────────────────────────

_build_commit_message() {
    sg_header "Craft Commit Message"

    # Select type
    local types
    types="$(sg_conventional_types)"
    local type_arr; read -ra type_arr <<< "$types"

    sg_info "Commit types:"
    local i
    for i in "${!type_arr[@]}"; do
        printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((i + 1))" "${type_arr[$i]}"
    done
    echo

    local type_choice commit_type
    while true; do
        printf "Select type [1-%d]: " "${#type_arr[@]}"
        read -r type_choice
        if [[ "$type_choice" =~ ^[0-9]+$ ]] && (( type_choice >= 1 && type_choice <= ${#type_arr[@]} )); then
            commit_type="${type_arr[$((type_choice - 1))]}"
            break
        fi
        sg_warn "Invalid selection."
    done

    # Scope (optional)
    local scope
    if [[ -n "${SG_COMMIT_SCOPES:-}" ]]; then
        sg_info "Allowed scopes: $SG_COMMIT_SCOPES"
    fi
    scope=$(sg_prompt "Scope (optional, press Enter to skip)" "")

    # Breaking change?
    local breaking=""
    if sg_confirm "Breaking change?" "n"; then
        breaking="!"
    fi

    # Subject
    local subject
    subject=$(sg_prompt "Subject (imperative mood, lowercase, no period)")

    # Body (optional)
    local body=""
    if sg_confirm "Add extended body?" "n"; then
        sg_info "Enter body (end with an empty line):"
        local line
        while IFS= read -r line; do
            [[ -z "$line" ]] && break
            body+="$line"$'\n'
        done
    fi

    # Ticket reference
    local ticket_ref=""
    local ticket
    ticket="$(sg_ticket_from_branch)"
    if [[ -n "$ticket" ]]; then
        ticket_ref="Refs: $ticket"
    elif [[ "${SG_REQUIRE_TICKET:-false}" == "true" ]]; then
        local manual_ticket
        manual_ticket=$(sg_prompt "Ticket reference (required)")
        ticket_ref="Refs: $manual_ticket"
    fi

    # Assemble
    local header
    if [[ -n "$scope" ]]; then
        header="$commit_type($scope)$breaking: $subject"
    else
        header="$commit_type$breaking: $subject"
    fi

    local message="$header"
    if [[ -n "$body" ]]; then
        message+=$'\n\n'"$body"
    fi
    if [[ -n "$ticket_ref" ]]; then
        message+=$'\n\n'"$ticket_ref"
    fi

    echo "$message"
}

# ─── Diff size check ────────────────────────────────────────────────────────

_check_diff_size() {
    local max_lines="${SG_MAX_DIFF_LINES:-200}"
    local diff_lines
    diff_lines=$(git diff --cached --stat 2>/dev/null | tail -1 || echo "")

    if [[ -z "$diff_lines" ]]; then
        return 0
    fi

    local insertions deletions
    insertions=$(echo "$diff_lines" | grep -oP '\d+(?= insertion)' || echo 0)
    deletions=$(echo "$diff_lines" | grep -oP '\d+(?= deletion)' || echo 0)
    local total=$(( insertions + deletions ))

    if (( total > max_lines )); then
        sg_warn "Large diff detected: $total lines changed (threshold: $max_lines)"
        sg_warn "Consider splitting into smaller, focused commits."
        echo
        sg_info "Staged files:"
        sg_staged_files | while read -r f; do
            printf "  %s\n" "$f"
        done
        echo
        if ! sg_confirm "Continue with this large commit?" "n"; then
            return 1
        fi
    else
        sg_success "Diff size OK: $total lines (limit: $max_lines)"
    fi
    return 0
}

# ─── Security scan gate ─────────────────────────────────────────────────────

_security_gate() {
    local phase="$1"

    if [[ "${SG_PRE_COMMIT_SCAN:-true}" != "true" && "$phase" == "commit" ]]; then
        return 0
    fi
    if [[ "${SG_PRE_PUSH_SCAN:-true}" != "true" && "$phase" == "push" ]]; then
        return 0
    fi

    sg_info "Running security scan ($phase gate)..."
    if _sg_cmd scan --path "$(git rev-parse --show-toplevel)" 2>/dev/null; then
        sg_success "Security scan passed."
        return 0
    else
        sg_warn "Security scan found potential issues."
        if sg_confirm "View findings?" "y"; then
            _sg_cmd scan --path "$(git rev-parse --show-toplevel)" 2>/dev/null || true
        fi
        if sg_confirm "Continue despite findings?" "n"; then
            sg_warn "Proceeding with known findings."
            return 0
        fi
        return 1
    fi
}

# ─── Create PR ──────────────────────────────────────────────────────────────

_create_pr() {
    local branch="$1" draft="${2:-true}"
    local platform
    platform="$(_detect_platform)"

    local title body
    title=$(sg_prompt "PR title" "$(echo "$branch" | sed 's|.*/||; s/-/ /g')")
    sg_info "Enter PR description (end with an empty line):"
    body=""
    local line
    while IFS= read -r line; do
        [[ -z "$line" ]] && break
        body+="$line"$'\n'
    done

    case "$platform" in
        github)
            local draft_flag=""
            [[ "$draft" == "true" ]] && draft_flag="--draft"
            sg_info "Creating GitHub Pull Request..."
            gh pr create --title "$title" --body "$body" $draft_flag 2>&1
            sg_success "Pull request created."
            sg_info "PR URL:"
            gh pr view --json url -q '.url' 2>/dev/null || true
            ;;
        gitlab)
            local wip_prefix=""
            [[ "$draft" == "true" ]] && wip_prefix="Draft: "
            sg_info "Creating GitLab Merge Request..."
            glab mr create --title "${wip_prefix}${title}" --description "$body" 2>&1
            sg_success "Merge request created."
            ;;
        standalone)
            sg_warn "No CLI tool detected (gh/glab). Create the PR manually."
            sg_info "Suggested title: $title"
            if [[ -n "$body" ]]; then
                sg_info "Suggested body:"
                echo "$body"
            fi
            ;;
    esac
}

# ─── Phase: START ────────────────────────────────────────────────────────────

phase_start() {
    sg_header "Phase 1: Start New Feature"

    local current_branch
    current_branch="$(sg_current_branch)"
    local default_branch
    default_branch="$(sg_default_branch)"

    # Warn if not on default branch
    if [[ "$current_branch" != "$default_branch" ]]; then
        sg_warn "You are on '$current_branch', not '$default_branch'."
        if ! sg_confirm "Create branch from '$current_branch' anyway?" "n"; then
            sg_info "Switching to $default_branch..."
            _sg_cmd checkout "$default_branch"
            sg_info "Pulling latest..."
            _sg_cmd pull "${SG_PRIMARY_REMOTE:-origin}" "$default_branch" 2>/dev/null || true
        fi
    else
        sg_info "Pulling latest changes on $default_branch..."
        _sg_cmd pull "${SG_PRIMARY_REMOTE:-origin}" "$default_branch" 2>/dev/null || true
    fi

    # Build branch name
    local branch_name
    branch_name="$(_build_branch_name)"

    sg_info "Creating branch: $branch_name"
    _sg_cmd checkout -b "$branch_name"
    sg_success "Branch '$branch_name' created and checked out."
    sg_undo_available

    # Push branch to set upstream
    if sg_has_remote; then
        if sg_confirm "Push branch to remote to set upstream?" "y"; then
            _sg_cmd push -u "${SG_PRIMARY_REMOTE:-origin}" "$branch_name"
            sg_success "Branch pushed to remote."

            # Create draft PR
            if sg_confirm "Create draft PR now?" "y"; then
                _create_pr "$branch_name" "true"
            fi
        fi
    fi

    # Offer securegit stack
    if command -v securegit &>/dev/null; then
        if sg_confirm "Initialize securegit stack for stacked PRs?" "n"; then
            sg_info "Initializing stack..."
            _sg_cmd stack init 2>/dev/null || sg_warn "Stack init not available in this securegit version."
        fi
    fi

    echo
    sg_divider
    sg_success "Feature branch ready. Run 'develop' phase to start coding."
}

# ─── Phase: DEVELOP ─────────────────────────────────────────────────────────

phase_develop() {
    sg_header "Phase 2: Development Cycle"

    local current_branch
    current_branch="$(sg_current_branch)"
    local default_branch
    default_branch="$(sg_default_branch)"

    # Ensure we are on a feature branch
    if sg_is_protected "$current_branch"; then
        sg_error "You are on protected branch '$current_branch'."
        sg_die "Switch to a feature branch first with 'start' phase."
    fi

    while true; do
        local dev_choice
        dev_choice=$(sg_menu "Development Actions" \
            "View status (staged / unstaged / untracked)" \
            "Stage changes interactively" \
            "Stage all changes" \
            "Craft commit (conventional format)" \
            "Quick commit (type message directly)" \
            "Push to remote" \
            "Sync with $default_branch (rebase)" \
            "Run security scan" \
            "View diff (staged)" \
            "View diff (unstaged)" \
            "Stash changes" \
            "Pop stash" \
            "Back to main menu")

        case "$dev_choice" in
            1)  # Status
                sg_header "Repository Status"
                _sg_cmd status
                echo
                local staged_count unstaged_count untracked_count
                staged_count=$(git diff --cached --name-only 2>/dev/null | wc -l)
                unstaged_count=$(git diff --name-only 2>/dev/null | wc -l)
                untracked_count=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l)
                printf "${_C_GREEN}Staged:${_C_RESET}    %d files\n" "$staged_count"
                printf "${_C_YELLOW}Unstaged:${_C_RESET}  %d files\n" "$unstaged_count"
                printf "${_C_RED}Untracked:${_C_RESET} %d files\n" "$untracked_count"
                ;;

            2)  # Stage interactively
                sg_header "Stage Changes"
                local unstaged_files
                unstaged_files=$(git diff --name-only 2>/dev/null)
                local untracked_files
                untracked_files=$(git ls-files --others --exclude-standard 2>/dev/null)

                if [[ -z "$unstaged_files" && -z "$untracked_files" ]]; then
                    sg_info "No changes to stage."
                    continue
                fi

                sg_info "Modified files:"
                local all_files=()
                while IFS= read -r f; do
                    [[ -n "$f" ]] && all_files+=("$f")
                done <<< "$unstaged_files"
                while IFS= read -r f; do
                    [[ -n "$f" ]] && all_files+=("$f")
                done <<< "$untracked_files"

                local idx
                for idx in "${!all_files[@]}"; do
                    printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((idx + 1))" "${all_files[$idx]}"
                done
                echo

                local stage_input
                printf "Enter file numbers to stage (comma-separated, or 'a' for all): "
                read -r stage_input

                if [[ "$stage_input" == "a" || "$stage_input" == "A" ]]; then
                    _sg_cmd add -A
                    sg_success "All changes staged."
                else
                    IFS=',' read -ra selections <<< "$stage_input"
                    for sel in "${selections[@]}"; do
                        sel=$(echo "$sel" | tr -d ' ')
                        if [[ "$sel" =~ ^[0-9]+$ ]] && (( sel >= 1 && sel <= ${#all_files[@]} )); then
                            _sg_cmd add "${all_files[$((sel - 1))]}"
                            sg_success "Staged: ${all_files[$((sel - 1))]}"
                        fi
                    done
                fi
                sg_undo_available
                ;;

            3)  # Stage all
                _sg_cmd add -A
                sg_success "All changes staged."
                sg_undo_available
                ;;

            4)  # Conventional commit
                local staged
                staged="$(sg_staged_files)"
                if [[ -z "$staged" ]]; then
                    sg_warn "No staged changes. Stage files first."
                    continue
                fi

                # Check diff size
                if ! _check_diff_size; then
                    continue
                fi

                # Security scan
                if [[ "${SG_PRE_COMMIT_SCAN:-true}" == "true" ]]; then
                    if ! _security_gate "commit"; then
                        sg_warn "Commit blocked by security scan."
                        continue
                    fi
                fi

                local msg
                msg="$(_build_commit_message)"

                sg_info "Commit message:"
                sg_divider
                echo "$msg"
                sg_divider

                if sg_confirm "Create this commit?" "y"; then
                    _sg_cmd commit -m "$msg"
                    sg_success "Commit created."
                    sg_undo_available
                else
                    sg_info "Commit cancelled."
                fi
                ;;

            5)  # Quick commit
                local staged
                staged="$(sg_staged_files)"
                if [[ -z "$staged" ]]; then
                    sg_warn "No staged changes. Stage files first."
                    continue
                fi

                if ! _check_diff_size; then
                    continue
                fi

                if [[ "${SG_PRE_COMMIT_SCAN:-true}" == "true" ]]; then
                    if ! _security_gate "commit"; then
                        sg_warn "Commit blocked by security scan."
                        continue
                    fi
                fi

                local quick_msg
                quick_msg=$(sg_prompt "Commit message")
                _sg_cmd commit -m "$quick_msg"
                sg_success "Commit created."
                sg_undo_available
                ;;

            6)  # Push
                if [[ "${SG_PRE_PUSH_SCAN:-true}" == "true" ]]; then
                    if ! _security_gate "push"; then
                        sg_warn "Push blocked by security scan."
                        continue
                    fi
                fi

                sg_info "Pushing to remote..."
                local remote="${SG_PRIMARY_REMOTE:-origin}"
                if ! git rev-parse --abbrev-ref --symbolic-full-name "@{u}" &>/dev/null; then
                    _sg_cmd push -u "$remote" "$current_branch"
                else
                    _sg_cmd push
                fi
                sg_success "Pushed to remote."
                sg_undo_available

                # Update PR status
                local platform
                platform="$(_detect_platform)"
                case "$platform" in
                    github)
                        sg_info "PR status:"
                        gh pr view --json state,title,url -q '"[\(.state)] \(.title)\n\(.url)"' 2>/dev/null || sg_info "No PR found for this branch."
                        ;;
                    gitlab)
                        sg_info "MR status:"
                        glab mr view 2>/dev/null || sg_info "No MR found for this branch."
                        ;;
                esac
                ;;

            7)  # Sync with default branch
                sg_info "Fetching latest from $default_branch..."
                _sg_cmd fetch "${SG_PRIMARY_REMOTE:-origin}" "$default_branch"

                local strategy
                strategy=$(sg_prompt "Rebase or merge from $default_branch?" "rebase")
                if [[ "$strategy" == "rebase" ]]; then
                    sg_info "Rebasing onto $default_branch..."
                    if _sg_cmd rebase "${SG_PRIMARY_REMOTE:-origin}/$default_branch"; then
                        sg_success "Rebase completed."
                    else
                        sg_error "Rebase conflicts detected. Resolve them, then run 'git rebase --continue'."
                    fi
                else
                    sg_info "Merging $default_branch..."
                    if _sg_cmd merge "${SG_PRIMARY_REMOTE:-origin}/$default_branch"; then
                        sg_success "Merge completed."
                    else
                        sg_error "Merge conflicts detected. Resolve them, then commit."
                    fi
                fi
                sg_undo_available
                ;;

            8)  # Security scan
                _security_gate "manual" || true
                ;;

            9)  # Diff staged
                sg_header "Staged Changes"
                if command -v securegit &>/dev/null; then
                    _sg_cmd diff --cached 2>/dev/null || git diff --cached
                else
                    git diff --cached
                fi
                ;;

            10) # Diff unstaged
                sg_header "Unstaged Changes"
                if command -v securegit &>/dev/null; then
                    _sg_cmd diff 2>/dev/null || git diff
                else
                    git diff
                fi
                ;;

            11) # Stash
                local stash_msg
                stash_msg=$(sg_prompt "Stash message (optional)" "WIP on $current_branch")
                _sg_cmd stash push -m "$stash_msg"
                sg_success "Changes stashed."
                sg_undo_available
                ;;

            12) # Pop stash
                _sg_cmd stash pop
                sg_success "Stash popped."
                sg_undo_available
                ;;

            13) # Back
                return 0
                ;;
        esac

        echo
    done
}

# ─── Phase: REVIEW ───────────────────────────────────────────────────────────

phase_review() {
    sg_header "Phase 3: Review Preparation"

    local current_branch
    current_branch="$(sg_current_branch)"
    local default_branch
    default_branch="$(sg_default_branch)"
    local platform
    platform="$(_detect_platform)"

    if sg_is_protected "$current_branch"; then
        sg_die "You are on protected branch '$current_branch'. Switch to a feature branch."
    fi

    while true; do
        local review_choice
        review_choice=$(sg_menu "Review Actions" \
            "Show compact diff against $default_branch" \
            "Show full diff against $default_branch" \
            "Show commit log for this branch" \
            "Show change statistics" \
            "Run security scan" \
            "Run quality gates (test + lint + scan)" \
            "Show PR/MR status" \
            "Mark PR as ready for review" \
            "Self-review checklist" \
            "Back to main menu")

        case "$review_choice" in
            1)  # Compact diff
                sg_header "Compact Diff: $current_branch vs $default_branch"
                if command -v securegit &>/dev/null; then
                    _sg_cmd diff "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch" 2>/dev/null \
                        || git diff --stat "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch"
                else
                    git diff --stat "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch"
                fi
                ;;

            2)  # Full diff
                sg_header "Full Diff: $current_branch vs $default_branch"
                git diff "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch"
                ;;

            3)  # Commit log
                sg_header "Commits on $current_branch"
                _sg_cmd log "${SG_PRIMARY_REMOTE:-origin}/$default_branch..HEAD" --oneline 2>/dev/null \
                    || git log "${SG_PRIMARY_REMOTE:-origin}/$default_branch..HEAD" --oneline
                ;;

            4)  # Change statistics
                sg_header "Change Statistics"
                local stats
                stats="$(git diff --shortstat "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch" 2>/dev/null || echo "Unable to compute stats")"
                echo "$stats"
                echo

                sg_info "Files changed:"
                git diff --name-only "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch" 2>/dev/null | while read -r f; do
                    local file_stat
                    file_stat="$(git diff --numstat "${SG_PRIMARY_REMOTE:-origin}/$default_branch...$current_branch" -- "$f" 2>/dev/null | awk '{printf "+%s/-%s", $1, $2}')"
                    printf "  %-50s %s\n" "$f" "$file_stat"
                done

                local commit_count
                commit_count=$(git rev-list --count "${SG_PRIMARY_REMOTE:-origin}/$default_branch..HEAD" 2>/dev/null || echo 0)
                echo
                printf "${_C_BOLD}Total commits:${_C_RESET} %s\n" "$commit_count"
                ;;

            5)  # Security scan
                _security_gate "review" || true
                ;;

            6)  # Quality gates
                sg_header "Running Quality Gates"

                local pass=true

                # Test
                sg_info "Running tests..."
                local test_cmd
                test_cmd="$(sg_detect_test_cmd)"
                if eval "$test_cmd" 2>&1; then
                    sg_success "Tests passed."
                else
                    sg_error "Tests failed."
                    pass=false
                fi

                # Lint
                sg_info "Running linter..."
                local lint_cmd
                lint_cmd="$(sg_detect_lint_cmd)"
                if eval "$lint_cmd" 2>&1; then
                    sg_success "Lint passed."
                else
                    sg_error "Lint failed."
                    pass=false
                fi

                # Security scan
                sg_info "Running security scan..."
                if _sg_cmd scan --path "$(git rev-parse --show-toplevel)" 2>/dev/null; then
                    sg_success "Security scan passed."
                else
                    sg_warn "Security scan found issues."
                    pass=false
                fi

                echo
                if [[ "$pass" == "true" ]]; then
                    sg_success "All quality gates passed."
                else
                    sg_error "Some quality gates failed. Review issues above."
                fi
                ;;

            7)  # PR/MR status
                sg_header "PR/MR Status"
                case "$platform" in
                    github)
                        gh pr view 2>/dev/null || sg_warn "No PR found for branch '$current_branch'."
                        echo
                        sg_info "PR checks:"
                        gh pr checks 2>/dev/null || true
                        ;;
                    gitlab)
                        glab mr view 2>/dev/null || sg_warn "No MR found for branch '$current_branch'."
                        ;;
                    standalone)
                        sg_info "No CLI tool detected. Check your PR status in the web UI."
                        sg_info "Branch: $current_branch"
                        local commit_count
                        commit_count=$(git rev-list --count "${SG_PRIMARY_REMOTE:-origin}/$default_branch..HEAD" 2>/dev/null || echo "?")
                        printf "${_C_BOLD}Commits ahead of %s:${_C_RESET} %s\n" "$default_branch" "$commit_count"
                        ;;
                esac
                ;;

            8)  # Mark ready
                case "$platform" in
                    github)
                        sg_info "Marking PR as ready for review..."
                        if gh pr ready 2>/dev/null; then
                            sg_success "PR marked as ready for review."
                        else
                            sg_error "Failed to mark PR as ready. Ensure a PR exists."
                        fi
                        ;;
                    gitlab)
                        sg_info "Removing Draft prefix from MR..."
                        local mr_title
                        mr_title=$(glab mr view --output json 2>/dev/null | grep -oP '"title"\s*:\s*"Draft: \K[^"]+' || echo "")
                        if [[ -n "$mr_title" ]]; then
                            glab mr update --title "$mr_title" 2>/dev/null
                            sg_success "MR marked as ready."
                        else
                            sg_warn "MR is already marked as ready or not found."
                        fi
                        ;;
                    standalone)
                        sg_info "Mark your PR as ready in the web UI."
                        ;;
                esac
                ;;

            9)  # Self-review checklist
                sg_header "Self-Review Checklist"
                cat <<'CHECKLIST'
  [ ] Code compiles / builds without warnings
  [ ] All tests pass
  [ ] Linter has no new warnings
  [ ] Security scan is clean
  [ ] No secrets, tokens, or credentials in code
  [ ] Changes match the ticket / issue description
  [ ] Breaking changes are documented
  [ ] Edge cases are handled
  [ ] Error messages are helpful
  [ ] Logging is appropriate (not too verbose, not too sparse)
  [ ] Documentation updated if needed
  [ ] Commit messages follow conventional format
  [ ] Diff is under threshold (no massive single commits)
  [ ] No leftover debug code or TODOs
CHECKLIST
                ;;

            10) # Back
                return 0
                ;;
        esac

        echo
    done
}

# ─── Phase: MERGE ────────────────────────────────────────────────────────────

phase_merge() {
    sg_header "Phase 4: Merge & Cleanup"

    local current_branch
    current_branch="$(sg_current_branch)"
    local default_branch
    default_branch="$(sg_default_branch)"
    local remote="${SG_PRIMARY_REMOTE:-origin}"
    local platform
    platform="$(_detect_platform)"

    if sg_is_protected "$current_branch"; then
        sg_die "You are on protected branch '$current_branch'. Switch to the feature branch to merge."
    fi

    # Pre-merge checks
    sg_info "Pre-merge checks..."

    # Check for uncommitted changes
    local status
    status="$(git status --porcelain 2>/dev/null)"
    if [[ -n "$status" ]]; then
        sg_error "Uncommitted changes detected."
        sg_die "Commit or stash your changes before merging."
    fi

    # Check if up to date with remote
    sg_info "Fetching latest from remote..."
    _sg_cmd fetch "$remote" 2>/dev/null || true

    local behind
    behind=$(git rev-list --count "HEAD..${remote}/${current_branch}" 2>/dev/null || echo 0)
    if (( behind > 0 )); then
        sg_warn "Local branch is $behind commit(s) behind remote."
        if sg_confirm "Pull latest changes?" "y"; then
            _sg_cmd pull "$remote" "$current_branch"
        fi
    fi

    # Check if default branch is ahead
    local default_behind
    default_behind=$(git rev-list --count "HEAD..${remote}/${default_branch}" 2>/dev/null || echo 0)
    if (( default_behind > 0 )); then
        sg_warn "$default_branch has $default_behind new commit(s) since your branch diverged."
        if sg_confirm "Rebase onto $default_branch first?" "y"; then
            _sg_cmd rebase "${remote}/${default_branch}"
            sg_success "Rebased onto $default_branch."
            if sg_confirm "Force-push rebased branch?" "y"; then
                _sg_cmd push --force-with-lease
                sg_success "Force-pushed with lease."
            fi
        fi
    fi

    # Final security scan
    sg_info "Final security scan before merge..."
    _security_gate "merge" || true

    # Merge strategy
    local strategy="${SG_DEFAULT_MERGE_STRATEGY:-squash}"
    sg_info "Default merge strategy: $strategy"
    if ! sg_confirm "Use '$strategy' merge strategy?" "y"; then
        local strat_choice
        strat_choice=$(sg_menu "Merge Strategy" "merge (standard merge commit)" "squash (squash all into one commit)" "rebase (rebase onto target)" "ff-only (fast-forward only)")
        case "$strat_choice" in
            1) strategy="merge" ;;
            2) strategy="squash" ;;
            3) strategy="rebase" ;;
            4) strategy="ff-only" ;;
        esac
    fi

    # Perform merge via platform or locally
    case "$platform" in
        github)
            sg_info "Merging via GitHub..."
            local gh_method
            case "$strategy" in
                merge)  gh_method="merge" ;;
                squash) gh_method="squash" ;;
                rebase) gh_method="rebase" ;;
                *)      gh_method="squash" ;;
            esac
            if gh pr merge --"$gh_method" --delete-branch 2>/dev/null; then
                sg_success "PR merged and branch deleted on remote."
            else
                sg_error "GitHub merge failed. Check PR status."
                return 1
            fi
            ;;
        gitlab)
            sg_info "Merging via GitLab..."
            if glab mr merge --squash --remove-source-branch 2>/dev/null; then
                sg_success "MR merged and branch deleted on remote."
            else
                sg_error "GitLab merge failed. Check MR status."
                return 1
            fi
            ;;
        standalone)
            sg_info "Performing local merge..."
            _sg_cmd checkout "$default_branch"
            _sg_cmd pull "$remote" "$default_branch" 2>/dev/null || true

            case "$strategy" in
                merge)
                    _sg_cmd merge "$current_branch"
                    ;;
                squash)
                    _sg_cmd merge --squash "$current_branch"
                    local squash_msg
                    squash_msg=$(sg_prompt "Squash commit message" "$(git log --oneline "${default_branch}..${current_branch}" | head -1)")
                    _sg_cmd commit -m "$squash_msg"
                    ;;
                rebase)
                    _sg_cmd rebase "$current_branch"
                    ;;
                ff-only)
                    if ! _sg_cmd merge --ff-only "$current_branch"; then
                        sg_error "Fast-forward not possible. The branch has diverged."
                        _sg_cmd checkout "$current_branch"
                        return 1
                    fi
                    ;;
            esac

            sg_success "Merged '$current_branch' into '$default_branch' ($strategy)."

            if sg_confirm "Push $default_branch to remote?" "y"; then
                _sg_cmd push "$remote" "$default_branch"
                sg_success "Pushed $default_branch."
            fi

            if sg_confirm "Delete local branch '$current_branch'?" "y"; then
                _sg_cmd branch -d "$current_branch"
                sg_success "Local branch deleted."
            fi

            if sg_confirm "Delete remote branch '$current_branch'?" "y"; then
                _sg_cmd push "$remote" --delete "$current_branch" 2>/dev/null || sg_warn "Remote branch may already be deleted."
                sg_success "Remote branch deleted."
            fi
            ;;
    esac

    # Cleanup: switch to default branch if not already there
    if [[ "$(sg_current_branch)" != "$default_branch" ]]; then
        _sg_cmd checkout "$default_branch" 2>/dev/null || true
    fi

    sg_undo_available

    echo
    sg_divider
    sg_success "Merge complete. Development flow finished."
    sg_info "Branch '$current_branch' merged into '$default_branch' using '$strategy' strategy."
}

# ─── Status view ─────────────────────────────────────────────────────────────

phase_status() {
    sg_header "Development Flow Status"

    local current_branch
    current_branch="$(sg_current_branch)"
    local default_branch
    default_branch="$(sg_default_branch)"
    local remote="${SG_PRIMARY_REMOTE:-origin}"
    local platform
    platform="$(_detect_platform)"

    printf "${_C_BOLD}Branch:${_C_RESET}        %s\n" "$current_branch"
    printf "${_C_BOLD}Default:${_C_RESET}       %s\n" "$default_branch"
    printf "${_C_BOLD}Platform:${_C_RESET}      %s\n" "$(_platform_name)"
    printf "${_C_BOLD}Language:${_C_RESET}      %s\n" "$(sg_detect_language)"
    echo

    # Ahead/behind
    _sg_cmd fetch "$remote" 2>/dev/null || true
    local ahead behind
    ahead=$(git rev-list --count "${remote}/${default_branch}..HEAD" 2>/dev/null || echo "?")
    behind=$(git rev-list --count "HEAD..${remote}/${default_branch}" 2>/dev/null || echo "?")
    printf "${_C_BOLD}Ahead of %s:${_C_RESET}  %s commits\n" "$default_branch" "$ahead"
    printf "${_C_BOLD}Behind %s:${_C_RESET}     %s commits\n" "$default_branch" "$behind"
    echo

    # Working tree status
    local staged unstaged untracked
    staged=$(git diff --cached --name-only 2>/dev/null | wc -l)
    unstaged=$(git diff --name-only 2>/dev/null | wc -l)
    untracked=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l)
    printf "${_C_GREEN}Staged:${_C_RESET}        %d files\n" "$staged"
    printf "${_C_YELLOW}Unstaged:${_C_RESET}      %d files\n" "$unstaged"
    printf "${_C_RED}Untracked:${_C_RESET}     %d files\n" "$untracked"
    echo

    # Protected branch?
    if sg_is_protected "$current_branch"; then
        sg_warn "You are on a protected branch."
    fi

    # Ticket
    local ticket
    ticket="$(sg_ticket_from_branch)"
    if [[ -n "$ticket" ]]; then
        printf "${_C_BOLD}Ticket:${_C_RESET}        %s\n" "$ticket"
    fi

    # PR status
    case "$platform" in
        github)
            echo
            sg_info "Pull Request:"
            gh pr view --json state,title,url,reviewDecision -q '"  [\(.state)] \(.title)\n  URL: \(.url)\n  Review: \(.reviewDecision // "none")"' 2>/dev/null \
                || sg_info "  No PR found for this branch."
            ;;
        gitlab)
            echo
            sg_info "Merge Request:"
            glab mr view 2>/dev/null || sg_info "  No MR found for this branch."
            ;;
    esac

    # Config summary
    echo
    sg_divider
    printf "${_C_DIM}Merge strategy: %s | Max diff: %s lines | Scan on commit: %s | Scan on push: %s${_C_RESET}\n" \
        "${SG_DEFAULT_MERGE_STRATEGY:-squash}" \
        "${SG_MAX_DIFF_LINES:-200}" \
        "${SG_PRE_COMMIT_SCAN:-true}" \
        "${SG_PRE_PUSH_SCAN:-true}"
}

# ─── Main ────────────────────────────────────────────────────────────────────

main() {
    sg_require_repo

    # Handle direct phase arguments
    case "${1:-}" in
        start)   phase_start; exit 0 ;;
        develop) phase_develop; exit 0 ;;
        review)  phase_review; exit 0 ;;
        merge)   phase_merge; exit 0 ;;
        status)  phase_status; exit 0 ;;
        --help|-h)
            echo "Usage: $0 [start|develop|review|merge|status|--help]"
            echo
            echo "Phases:"
            echo "  start     Create feature branch and draft PR"
            echo "  develop   Iterative development with staging, commits, scans"
            echo "  review    Prepare for code review"
            echo "  merge     Merge, cleanup, and close"
            echo "  status    Show current flow status"
            exit 0
            ;;
    esac

    # Interactive menu
    while true; do
        phase_status
        echo

        local choice
        choice=$(sg_menu "Development Flow" \
            "Start — Create feature branch & draft PR" \
            "Develop — Stage, commit, push, scan" \
            "Review — Prepare for code review" \
            "Merge — Merge & cleanup" \
            "Status — Refresh status view" \
            "Exit")

        case "$choice" in
            1) phase_start ;;
            2) phase_develop ;;
            3) phase_review ;;
            4) phase_merge ;;
            5) phase_status ;;
            6)
                sg_success "Done."
                exit 0
                ;;
        esac

        echo
    done
}

main "$@"
