#!/usr/bin/env bash

set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  paperclip-upload-artifact.sh FILE [options]

Uploads a generated file from the current workspace to the current Paperclip
issue, then creates an attachment-backed artifact work product by default.

Required environment for live uploads:
  PAPERCLIP_API_URL, PAPERCLIP_API_KEY, PAPERCLIP_COMPANY_ID, PAPERCLIP_TASK_ID, PAPERCLIP_RUN_ID

Options:
  --issue-id ID          Issue id to attach to (default: PAPERCLIP_TASK_ID)
  --company-id ID        Company id (default: PAPERCLIP_COMPANY_ID)
  --title TEXT           Work product title (default: file basename)
  --summary TEXT         Work product summary
  --content-type TYPE    Override detected upload content type
  --status STATUS        Work product status (default: ready_for_review)
  --no-work-product      Only upload the issue attachment
  --no-primary           Do not mark the artifact work product primary for its type
  --output FORMAT        markdown or json (default: markdown)
  --dry-run              Print resolved upload settings without calling the API
  --help, -h             Show this help

Examples:
  scripts/paperclip-upload-artifact.sh dist/demo.mp4 \
    --title "Demo video render" \
    --summary "MP4 render for board review"

  scripts/paperclip-upload-artifact.sh out/walkthrough.webm \
    --title "Walkthrough video" \
    --content-type video/webm
EOF
}

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    printf 'Missing required command: %s\n' "$1" >&2
    exit 1
  fi
}

json_bool() {
  if [[ "${1:-0}" == "1" ]]; then
    printf 'true'
  else
    printf 'false'
  fi
}

detect_content_type() {
  local path="$1"
  local lower
  lower="$(printf '%s' "$path" | tr '[:upper:]' '[:lower:]')"

  case "$lower" in
    *.mp4|*.m4v) printf 'video/mp4' ;;
    *.webm) printf 'video/webm' ;;
    *.mov|*.qt) printf 'video/quicktime' ;;
    *.png) printf 'image/png' ;;
    *.jpg|*.jpeg) printf 'image/jpeg' ;;
    *.gif) printf 'image/gif' ;;
    *.webp) printf 'image/webp' ;;
    *.svg) printf 'image/svg+xml' ;;
    *.pdf) printf 'application/pdf' ;;
    *.txt|*.log) printf 'text/plain' ;;
    *.md|*.markdown) printf 'text/markdown' ;;
    *.json) printf 'application/json' ;;
    *.csv) printf 'text/csv' ;;
    *.html|*.htm) printf 'text/html' ;;
    *.zip) printf 'application/zip' ;;
    *)
      if command -v file >/dev/null 2>&1; then
        file --brief --mime-type "$path"
      else
        printf 'application/octet-stream'
      fi
      ;;
  esac
}

request_json() {
  local method="$1"
  local url="$2"
  local body="${3:-}"
  local response_file
  local status_code

  response_file="$(mktemp)"
  if [[ -n "$body" ]]; then
    status_code="$(
      curl -sS -X "$method" -w '%{http_code}' -o "$response_file" \
        "$url" \
        -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
        -H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
        -H 'Content-Type: application/json' \
        --data-binary "$body"
    )"
  else
    status_code="$(
      curl -sS -X "$method" -w '%{http_code}' -o "$response_file" \
        "$url" \
        -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
        -H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID"
    )"
  fi

  if [[ "$status_code" -lt 200 || "$status_code" -ge 300 ]]; then
    printf 'Request failed (%s): %s\n' "$status_code" "$url" >&2
    cat "$response_file" >&2
    printf '\n' >&2
    rm -f "$response_file"
    exit 1
  fi

  cat "$response_file"
  rm -f "$response_file"
}

upload_file() {
  local url="$1"
  local path="$2"
  local content_type="$3"
  local escaped_path
  local response_file
  local status_code

  escaped_path="${path//\\/\\\\}"
  escaped_path="${escaped_path//\"/\\\"}"
  response_file="$(mktemp)"
  status_code="$(
    curl -sS -X POST -w '%{http_code}' -o "$response_file" \
      "$url" \
      -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
      -H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
      -F "file=@\"${escaped_path}\";type=${content_type}"
  )"

  if [[ "$status_code" -lt 200 || "$status_code" -ge 300 ]]; then
    printf 'Upload failed (%s): %s\n' "$status_code" "$url" >&2
    cat "$response_file" >&2
    printf '\n' >&2
    rm -f "$response_file"
    exit 1
  fi

  cat "$response_file"
  rm -f "$response_file"
}

file_path=""
issue_id="${PAPERCLIP_TASK_ID:-}"
company_id="${PAPERCLIP_COMPANY_ID:-}"
title=""
summary=""
content_type=""
status="ready_for_review"
create_work_product=1
is_primary=1
output_format="markdown"
dry_run=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --issue-id)
      issue_id="${2:-}"
      shift 2
      ;;
    --company-id)
      company_id="${2:-}"
      shift 2
      ;;
    --title)
      title="${2:-}"
      shift 2
      ;;
    --summary)
      summary="${2:-}"
      shift 2
      ;;
    --content-type)
      content_type="${2:-}"
      shift 2
      ;;
    --status)
      status="${2:-}"
      shift 2
      ;;
    --no-work-product)
      create_work_product=0
      shift
      ;;
    --no-primary)
      is_primary=0
      shift
      ;;
    --output)
      output_format="${2:-}"
      shift 2
      ;;
    --dry-run)
      dry_run=1
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    --*)
      printf 'Unknown argument: %s\n' "$1" >&2
      usage >&2
      exit 1
      ;;
    *)
      if [[ -n "$file_path" ]]; then
        printf 'Unexpected positional argument: %s\n' "$1" >&2
        usage >&2
        exit 1
      fi
      file_path="$1"
      shift
      ;;
  esac
done

if [[ -z "$file_path" ]]; then
  printf 'Missing file path.\n' >&2
  usage >&2
  exit 1
fi

if [[ ! -f "$file_path" ]]; then
  printf 'Artifact file does not exist: %s\n' "$file_path" >&2
  exit 1
fi

if [[ "$output_format" != "markdown" && "$output_format" != "json" ]]; then
  printf 'Unsupported output format: %s\n' "$output_format" >&2
  exit 1
fi

require_command curl
require_command jq

if [[ -z "$title" ]]; then
  title="$(basename "$file_path")"
fi

if [[ -z "$content_type" ]]; then
  content_type="$(detect_content_type "$file_path")"
fi

if [[ "$dry_run" == "1" ]]; then
  create_work_product_json="$(json_bool "$create_work_product")"
  is_primary_json="$(json_bool "$is_primary")"
  jq -n \
    --arg file "$file_path" \
    --arg issueId "$issue_id" \
    --arg companyId "$company_id" \
    --arg title "$title" \
    --arg summary "$summary" \
    --arg contentType "$content_type" \
    --arg status "$status" \
    --argjson createWorkProduct "$create_work_product_json" \
    --argjson isPrimary "$is_primary_json" \
    '{file: $file, issueId: $issueId, companyId: $companyId, title: $title, summary: $summary, contentType: $contentType, status: $status, createWorkProduct: $createWorkProduct, isPrimary: $isPrimary}'
  exit 0
fi

if [[ -z "${PAPERCLIP_API_URL:-}" || -z "${PAPERCLIP_API_KEY:-}" || -z "${PAPERCLIP_RUN_ID:-}" ]]; then
  printf 'Missing PAPERCLIP_API_URL, PAPERCLIP_API_KEY, or PAPERCLIP_RUN_ID.\n' >&2
  exit 1
fi

if [[ -z "$issue_id" || -z "$company_id" ]]; then
  printf 'Missing issue or company id. Pass --issue-id/--company-id or set PAPERCLIP_TASK_ID/PAPERCLIP_COMPANY_ID.\n' >&2
  exit 1
fi

api_base="${PAPERCLIP_API_URL%/}/api"
attachment="$(
  upload_file \
    "$api_base/companies/$company_id/issues/$issue_id/attachments" \
    "$file_path" \
    "$content_type"
)"

work_product="null"
if [[ "$create_work_product" == "1" ]]; then
  is_primary_json="$(json_bool "$is_primary")"
  attachment_id="$(jq -r '.id // empty' <<<"$attachment")"
  byte_size="$(jq -r '.byteSize // 0' <<<"$attachment")"
  content_path="$(jq -r '.contentPath // empty' <<<"$attachment")"
  open_path="$(jq -r '.openPath // .contentPath // empty' <<<"$attachment")"
  download_path="$(jq -r '.downloadPath // (if .contentPath then (.contentPath + "?download=1") else "" end)' <<<"$attachment")"
  original_filename="$(jq -r '.originalFilename // empty' <<<"$attachment")"

  if [[ -z "$attachment_id" || -z "$content_path" || -z "$download_path" ]]; then
    printf 'Upload response did not include attachment path metadata.\n' >&2
    printf '%s\n' "$attachment" >&2
    exit 1
  fi

  work_product_payload="$(
    jq -nc \
      --arg title "$title" \
      --arg summary "$summary" \
      --arg status "$status" \
      --arg runId "$PAPERCLIP_RUN_ID" \
      --arg attachmentId "$attachment_id" \
      --arg contentType "$content_type" \
      --argjson byteSize "$byte_size" \
      --arg contentPath "$content_path" \
      --arg openPath "$open_path" \
      --arg downloadPath "$download_path" \
      --arg originalFilename "$original_filename" \
      --argjson isPrimary "$is_primary_json" \
      '{
        type: "artifact",
        provider: "paperclip",
        title: $title,
        status: $status,
        reviewState: "none",
        isPrimary: $isPrimary,
        healthStatus: "unknown",
        summary: (if $summary == "" then null else $summary end),
        createdByRunId: $runId,
        metadata: {
          attachmentId: $attachmentId,
          contentType: $contentType,
          byteSize: $byteSize,
          contentPath: $contentPath,
          openPath: $openPath,
          downloadPath: $downloadPath,
          originalFilename: (if $originalFilename == "" then null else $originalFilename end)
        }
      }'
  )"

  work_product="$(
    request_json \
      POST \
      "$api_base/issues/$issue_id/work-products" \
      "$work_product_payload"
  )"
fi

if [[ "$output_format" == "json" ]]; then
  jq -n --argjson attachment "$attachment" --argjson workProduct "$work_product" \
    '{attachment: $attachment, workProduct: $workProduct}'
  exit 0
fi

content_path="$(jq -r '.contentPath // empty' <<<"$attachment")"
download_path="$(jq -r '.downloadPath // (if .contentPath then (.contentPath + "?download=1") else "" end)' <<<"$attachment")"
attachment_id="$(jq -r '.id // empty' <<<"$attachment")"
work_product_id="$(jq -r '.id // empty' <<<"$work_product")"

printf 'Uploaded artifact\n\n'
printf -- '- Attachment: [%s](%s)\n' "$title" "$content_path"
printf -- '- Download: [%s](%s)\n' "$title" "$download_path"
printf -- '- Attachment ID: `%s`\n' "$attachment_id"
if [[ -n "$work_product_id" ]]; then
  printf -- '- Work product ID: `%s`\n' "$work_product_id"
fi
printf '\nFinal comment snippet:\n\n'
printf -- '- Artifact: [%s](%s)\n' "$title" "$content_path"
