---
- name: Copy staging data to test environment
  hosts: all
  become: true

  vars:
    staging_db: church_website_staging
    test_db: church_website_test
    test_db_user: church_website_test
    test_container: app-test
    test_port: 3002
    test_image: "church-website:test"

  tasks:
    # ── Phase 1: Pre-flight ───────────────────────────────────────────
    - name: Verify postgres container is running
      ansible.builtin.shell: docker ps --filter name=^{{ postgres_container_name }}$ --format '{{ '{{' }}.Status{{ '}}' }}'
      register: pg_status
      changed_when: false
      failed_when: "'Up' not in pg_status.stdout"

    - name: Verify staging database exists
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{ staging_db }}'"
      register: staging_exists
      changed_when: false
      failed_when: "'1' not in staging_exists.stdout"

    # ── Phase 2: Stop test app ────────────────────────────────────────
    - name: Stop test container
      ansible.builtin.shell: docker stop {{ test_container }} 2>/dev/null || true
      changed_when: false

    - name: Remove test container
      ansible.builtin.shell: docker rm {{ test_container }} 2>/dev/null || true
      changed_when: false

    # ── Phase 3: Database copy ────────────────────────────────────────
    - name: Terminate connections to test database
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -c
        "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{{ test_db }}' AND pid <> pg_backend_pid();"
      changed_when: false

    - name: Drop test database
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -c "DROP DATABASE IF EXISTS {{ test_db }};"

    - name: Create test database
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -c "CREATE DATABASE {{ test_db }} OWNER {{ test_db_user }};"

    - name: Enable PostGIS extension on test database
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -d {{ test_db }} -c "CREATE EXTENSION IF NOT EXISTS postgis;"

    - name: Dump staging and restore into test
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        bash -c "pg_dump -U postgres --no-owner --no-acl {{ staging_db }} | psql -U postgres -d {{ test_db }}"

    - name: Reassign ownership to test user
      ansible.builtin.shell: |
        docker exec {{ postgres_container_name }} psql -U postgres -d {{ test_db }} -c "
          DO \$\$
          DECLARE
            r RECORD;
          BEGIN
            FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP
              EXECUTE 'ALTER TABLE public.' || quote_ident(r.tablename) || ' OWNER TO {{ test_db_user }}';
            END LOOP;
            FOR r IN SELECT sequencename FROM pg_sequences WHERE schemaname = 'public' LOOP
              EXECUTE 'ALTER SEQUENCE public.' || quote_ident(r.sequencename) || ' OWNER TO {{ test_db_user }}';
            END LOOP;
            FOR r IN SELECT typname FROM pg_type t
              WHERE t.typnamespace = 'public'::regnamespace
                AND t.typtype = 'e'
                AND NOT EXISTS (
                  SELECT 1 FROM pg_depend d
                  WHERE d.objid = t.oid AND d.deptype = 'e'
                )
            LOOP
              EXECUTE 'ALTER TYPE public.' || quote_ident(r.typname) || ' OWNER TO {{ test_db_user }}';
            END LOOP;
          END
          \$\$;
        "

    - name: Verify tables exist in test database
      ansible.builtin.shell: >
        docker exec {{ postgres_container_name }}
        psql -U postgres -d {{ test_db }} -tAc "SELECT count(*) FROM pg_tables WHERE schemaname = 'public';"
      register: table_count
      changed_when: false
      failed_when: "table_count.stdout | int < 1"

    # ── Phase 4: Volume copy ─────────────────────────────────────────
    - name: Copy media volume from staging to test
      ansible.builtin.shell: >
        docker run --rm
        -v uploads-staging-media:/source:ro
        -v uploads-test-media:/target
        alpine sh -c "rm -rf /target/* && cp -a /source/. /target/"

    - name: Copy documents volume from staging to test
      ansible.builtin.shell: >
        docker run --rm
        -v uploads-staging-documents:/source:ro
        -v uploads-test-documents:/target
        alpine sh -c "rm -rf /target/* && cp -a /source/. /target/"

    # ── Phase 5: Restart test app ─────────────────────────────────────
    - name: Start test container
      ansible.builtin.shell: >
        docker run -d
        --name {{ test_container }}
        --restart unless-stopped
        --network {{ docker_network }}
        --env-file {{ envs_dir }}/test/.env
        -v uploads-test-media:/app/media
        -v uploads-test-documents:/app/documents
        -p 127.0.0.1:{{ test_port }}:3000
        {{ test_image }}

    - name: Fix volume permissions
      ansible.builtin.shell: >
        docker exec -u 0 {{ test_container }}
        chown -R 1001:1001 /app/media /app/documents

    # ── Phase 6: Health check ─────────────────────────────────────────
    - name: Wait for test app to be healthy
      ansible.builtin.uri:
        url: "http://127.0.0.1:{{ test_port }}"
        method: GET
        status_code: [200, 301, 302]
      register: health
      retries: 10
      delay: 5
      until: health.status in [200, 301, 302]

    - name: Print summary
      ansible.builtin.debug:
        msg: |
          Staging → Test copy complete!
          - Database: {{ staging_db }} → {{ test_db }} ({{ table_count.stdout }} tables)
          - Media & documents volumes copied
          - Test app running on port {{ test_port }}
          - Health check: HTTP {{ health.status }}
          - URL: https://mutter-teresa-test.skick.app
